1 // Copyright 2023 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gn/resolved_target_data.h"
6
7 #include "gn/test_with_scope.h"
8 #include "util/test/test.h"
9
10 // Tests that lib[_dir]s are inherited across deps boundaries for static
11 // libraries but not executables.
TEST(ResolvedTargetDataTest,GetTargetDeps)12 TEST(ResolvedTargetDataTest, GetTargetDeps) {
13 TestWithScope setup;
14 Err err;
15
16 TestTarget a(setup, "//foo:a", Target::GROUP);
17 TestTarget b(setup, "//foo:b", Target::GROUP);
18 TestTarget c(setup, "//foo:c", Target::GROUP);
19 TestTarget d(setup, "//foo:d", Target::GROUP);
20 TestTarget e(setup, "//foo:e", Target::GROUP);
21
22 a.private_deps().push_back(LabelTargetPair(&b));
23 a.private_deps().push_back(LabelTargetPair(&c));
24 a.public_deps().push_back(LabelTargetPair(&d));
25 a.data_deps().push_back(LabelTargetPair(&e));
26
27 b.private_deps().push_back(LabelTargetPair(&e));
28
29 ASSERT_TRUE(e.OnResolved(&err));
30 ASSERT_TRUE(d.OnResolved(&err));
31 ASSERT_TRUE(c.OnResolved(&err));
32 ASSERT_TRUE(b.OnResolved(&err));
33 ASSERT_TRUE(a.OnResolved(&err));
34
35 ResolvedTargetData resolved;
36
37 const auto& a_deps = resolved.GetTargetDeps(&a);
38 EXPECT_EQ(a_deps.size(), 4u);
39 EXPECT_EQ(a_deps.private_deps().size(), 2u);
40 EXPECT_EQ(a_deps.private_deps()[0], &b);
41 EXPECT_EQ(a_deps.private_deps()[1], &c);
42 EXPECT_EQ(a_deps.public_deps().size(), 1u);
43 EXPECT_EQ(a_deps.public_deps()[0], &d);
44 EXPECT_EQ(a_deps.data_deps().size(), 1u);
45 EXPECT_EQ(a_deps.data_deps()[0], &e);
46
47 const auto& b_deps = resolved.GetTargetDeps(&b);
48 EXPECT_EQ(b_deps.size(), 1u);
49 EXPECT_EQ(b_deps.private_deps().size(), 1u);
50 EXPECT_EQ(b_deps.private_deps()[0], &e);
51 EXPECT_EQ(b_deps.public_deps().size(), 0u);
52 EXPECT_EQ(b_deps.data_deps().size(), 0u);
53 }
54
55 // Tests that lib[_dir]s are inherited across deps boundaries for static
56 // libraries but not executables.
TEST(ResolvedTargetDataTest,LibInheritance)57 TEST(ResolvedTargetDataTest, LibInheritance) {
58 TestWithScope setup;
59 Err err;
60
61 ResolvedTargetData resolved;
62
63 const LibFile lib("foo");
64 const SourceDir libdir("/foo_dir/");
65
66 // Leaf target with ldflags set.
67 TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
68 z.config_values().libs().push_back(lib);
69 z.config_values().lib_dirs().push_back(libdir);
70 ASSERT_TRUE(z.OnResolved(&err));
71
72 // All lib[_dir]s should be set when target is resolved.
73 const auto& all_libs = resolved.GetLinkedLibraries(&z);
74 ASSERT_EQ(1u, all_libs.size());
75 EXPECT_EQ(lib, all_libs[0]);
76
77 const auto& all_lib_dirs = resolved.GetLinkedLibraryDirs(&z);
78 ASSERT_EQ(1u, all_lib_dirs.size());
79 EXPECT_EQ(libdir, all_lib_dirs[0]);
80
81 // Shared library target should inherit the libs from the static library
82 // and its own. Its own flag should be before the inherited one.
83 const LibFile second_lib("bar");
84 const SourceDir second_libdir("/bar_dir/");
85 TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
86 shared.config_values().libs().push_back(second_lib);
87 shared.config_values().lib_dirs().push_back(second_libdir);
88 shared.private_deps().push_back(LabelTargetPair(&z));
89 ASSERT_TRUE(shared.OnResolved(&err));
90
91 const auto& all_libs2 = resolved.GetLinkedLibraries(&shared);
92 ASSERT_EQ(2u, all_libs2.size());
93 EXPECT_EQ(second_lib, all_libs2[0]);
94 EXPECT_EQ(lib, all_libs2[1]);
95
96 const auto& all_lib_dirs2 = resolved.GetLinkedLibraryDirs(&shared);
97 ASSERT_EQ(2u, all_lib_dirs2.size());
98 EXPECT_EQ(second_libdir, all_lib_dirs2[0]);
99 EXPECT_EQ(libdir, all_lib_dirs2[1]);
100
101 // Executable target shouldn't get either by depending on shared.
102 TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
103 exec.private_deps().push_back(LabelTargetPair(&shared));
104 ASSERT_TRUE(exec.OnResolved(&err));
105
106 const auto& all_libs3 = resolved.GetLinkedLibraries(&exec);
107 EXPECT_EQ(0u, all_libs3.size());
108
109 const auto& all_lib_dirs3 = resolved.GetLinkedLibraryDirs(&exec);
110 EXPECT_EQ(0u, all_lib_dirs3.size());
111 }
112
113 // Tests that framework[_dir]s are inherited across deps boundaries for static
114 // libraries but not executables.
TEST(ResolvedTargetDataTest,FrameworkInheritance)115 TEST(ResolvedTargetDataTest, FrameworkInheritance) {
116 TestWithScope setup;
117 Err err;
118
119 const std::string framework("Foo.framework");
120 const SourceDir frameworkdir("//out/foo/");
121
122 // Leaf target with ldflags set.
123 TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
124 z.config_values().frameworks().push_back(framework);
125 z.config_values().framework_dirs().push_back(frameworkdir);
126 ASSERT_TRUE(z.OnResolved(&err));
127
128 ResolvedTargetData resolved;
129
130 // All framework[_dir]s should be set when target is resolved.
131 const auto& frameworks = resolved.GetLinkedFrameworks(&z);
132 ASSERT_EQ(1u, frameworks.size());
133 EXPECT_EQ(framework, frameworks[0]);
134
135 const auto& framework_dirs = resolved.GetLinkedFrameworkDirs(&z);
136 ASSERT_EQ(1u, framework_dirs.size());
137 EXPECT_EQ(frameworkdir, framework_dirs[0]);
138
139 // Shared library target should inherit the libs from the static library
140 // and its own. Its own flag should be before the inherited one.
141 const std::string second_framework("Bar.framework");
142 const SourceDir second_frameworkdir("//out/bar/");
143 TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
144 shared.config_values().frameworks().push_back(second_framework);
145 shared.config_values().framework_dirs().push_back(second_frameworkdir);
146 shared.private_deps().push_back(LabelTargetPair(&z));
147 ASSERT_TRUE(shared.OnResolved(&err));
148
149 const auto& frameworks2 = resolved.GetLinkedFrameworks(&shared);
150 ASSERT_EQ(2u, frameworks2.size());
151 EXPECT_EQ(second_framework, frameworks2[0]);
152 EXPECT_EQ(framework, frameworks2[1]);
153
154 const auto& framework_dirs2 = resolved.GetLinkedFrameworkDirs(&shared);
155 ASSERT_EQ(2u, framework_dirs2.size());
156 EXPECT_EQ(second_frameworkdir, framework_dirs2[0]);
157 EXPECT_EQ(frameworkdir, framework_dirs2[1]);
158
159 // Executable target shouldn't get either by depending on shared.
160 TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
161 exec.private_deps().push_back(LabelTargetPair(&shared));
162 ASSERT_TRUE(exec.OnResolved(&err));
163
164 const auto& frameworks3 = resolved.GetLinkedFrameworks(&exec);
165 EXPECT_EQ(0u, frameworks3.size());
166
167 const auto& framework_dirs3 = resolved.GetLinkedFrameworkDirs(&exec);
168 EXPECT_EQ(0u, framework_dirs3.size());
169 }
170
TEST(ResolvedTargetDataTest,InheritLibs)171 TEST(ResolvedTargetDataTest, InheritLibs) {
172 TestWithScope setup;
173 Err err;
174
175 // Create a dependency chain:
176 // A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
177 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
178 TestTarget b(setup, "//foo:b", Target::SHARED_LIBRARY);
179 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
180 TestTarget d(setup, "//foo:d", Target::SOURCE_SET);
181 a.private_deps().push_back(LabelTargetPair(&b));
182 b.private_deps().push_back(LabelTargetPair(&c));
183 c.private_deps().push_back(LabelTargetPair(&d));
184
185 ASSERT_TRUE(d.OnResolved(&err));
186 ASSERT_TRUE(c.OnResolved(&err));
187 ASSERT_TRUE(b.OnResolved(&err));
188 ASSERT_TRUE(a.OnResolved(&err));
189
190 ResolvedTargetData resolved;
191
192 // C should have D in its inherited libs.
193 const auto& c_inherited_libs = resolved.GetInheritedLibraries(&c);
194 ASSERT_EQ(1u, c_inherited_libs.size());
195 EXPECT_EQ(&d, c_inherited_libs[0].target());
196
197 // B should have C and D in its inherited libs.
198 const auto& b_inherited = resolved.GetInheritedLibraries(&b);
199 ASSERT_EQ(2u, b_inherited.size());
200 EXPECT_EQ(&c, b_inherited[0].target());
201 EXPECT_EQ(&d, b_inherited[1].target());
202
203 // A should have B in its inherited libs, but not any others (the shared
204 // library will include the static library and source set).
205 const auto& a_inherited = resolved.GetInheritedLibraries(&a);
206 ASSERT_EQ(1u, a_inherited.size());
207 EXPECT_EQ(&b, a_inherited[0].target());
208 }
209
TEST(ResolvedTargetData,NoActionDepPropgation)210 TEST(ResolvedTargetData, NoActionDepPropgation) {
211 TestWithScope setup;
212 Err err;
213 ResolvedTargetData resolved;
214 // Create a dependency chain:
215 // A (exe) -> B (action) -> C (source_set)
216 {
217 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
218 TestTarget b(setup, "//foo:b", Target::ACTION);
219 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
220
221 a.private_deps().push_back(LabelTargetPair(&b));
222 b.private_deps().push_back(LabelTargetPair(&c));
223
224 ASSERT_TRUE(c.OnResolved(&err));
225 ASSERT_TRUE(b.OnResolved(&err));
226 ASSERT_TRUE(a.OnResolved(&err));
227
228 // The executable should not have inherited the source set across the
229 // action.
230 ASSERT_TRUE(resolved.GetInheritedLibraries(&a).empty());
231 }
232 }
233
TEST(ResolvedTargetDataTest,InheritCompleteStaticLib)234 TEST(ResolvedTargetDataTest, InheritCompleteStaticLib) {
235 TestWithScope setup;
236 Err err;
237
238 ResolvedTargetData resolved;
239
240 // Create a dependency chain:
241 // A (executable) -> B (complete static lib) -> C (source set)
242 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
243 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
244 b.set_complete_static_lib(true);
245
246 const LibFile lib("foo");
247 const SourceDir lib_dir("/foo_dir/");
248 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
249 c.config_values().libs().push_back(lib);
250 c.config_values().lib_dirs().push_back(lib_dir);
251
252 a.public_deps().push_back(LabelTargetPair(&b));
253 b.public_deps().push_back(LabelTargetPair(&c));
254
255 ASSERT_TRUE(c.OnResolved(&err));
256 ASSERT_TRUE(b.OnResolved(&err));
257 ASSERT_TRUE(a.OnResolved(&err));
258
259 // B should have C in its inherited libs.
260 const auto& b_inherited = resolved.GetInheritedLibraries(&b);
261 ASSERT_EQ(1u, b_inherited.size());
262 EXPECT_EQ(&c, b_inherited[0].target());
263
264 // A should have B in its inherited libs, but not any others (the complete
265 // static library will include the source set).
266 const auto& a_inherited = resolved.GetInheritedLibraries(&a);
267 ASSERT_EQ(1u, a_inherited.size());
268 EXPECT_EQ(&b, a_inherited[0].target());
269
270 // A should inherit the libs and lib_dirs from the C.
271 const auto& a_libs = resolved.GetLinkedLibraries(&a);
272 ASSERT_EQ(1u, a_libs.size());
273 EXPECT_EQ(lib, a_libs[0]);
274
275 const auto& a_lib_dirs = resolved.GetLinkedLibraryDirs(&a);
276 ASSERT_EQ(1u, a_lib_dirs.size());
277 EXPECT_EQ(lib_dir, a_lib_dirs[0]);
278 }
279
TEST(ResolvedTargetDataTest,InheritCompleteStaticLibStaticLibDeps)280 TEST(ResolvedTargetDataTest, InheritCompleteStaticLibStaticLibDeps) {
281 TestWithScope setup;
282 Err err;
283
284 // Create a dependency chain:
285 // A (executable) -> B (complete static lib) -> C (static lib)
286 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
287 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
288 b.set_complete_static_lib(true);
289 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
290 a.public_deps().push_back(LabelTargetPair(&b));
291 b.public_deps().push_back(LabelTargetPair(&c));
292
293 ASSERT_TRUE(c.OnResolved(&err));
294 ASSERT_TRUE(b.OnResolved(&err));
295 ASSERT_TRUE(a.OnResolved(&err));
296
297 ResolvedTargetData resolved;
298
299 // B should have C in its inherited libs.
300 const auto& b_inherited = resolved.GetInheritedLibraries(&b);
301 ASSERT_EQ(1u, b_inherited.size());
302 EXPECT_EQ(&c, b_inherited[0].target());
303
304 // A should have B in its inherited libs, but not any others (the complete
305 // static library will include the static library).
306 const auto& a_inherited = resolved.GetInheritedLibraries(&a);
307 ASSERT_EQ(1u, a_inherited.size());
308 EXPECT_EQ(&b, a_inherited[0].target());
309 }
310
TEST(ResolvedTargetDataTest,InheritCompleteStaticLibInheritedCompleteStaticLibDeps)311 TEST(ResolvedTargetDataTest,
312 InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
313 TestWithScope setup;
314 Err err;
315
316 // Create a dependency chain:
317 // A (executable) -> B (complete static lib) -> C (complete static lib)
318 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
319 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
320 b.set_complete_static_lib(true);
321 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
322 c.set_complete_static_lib(true);
323
324 a.private_deps().push_back(LabelTargetPair(&b));
325 b.private_deps().push_back(LabelTargetPair(&c));
326
327 ASSERT_TRUE(c.OnResolved(&err));
328 ASSERT_TRUE(b.OnResolved(&err));
329 ASSERT_TRUE(a.OnResolved(&err));
330
331 ResolvedTargetData resolved;
332
333 // B should have C in its inherited libs.
334 const auto& b_inherited = resolved.GetInheritedLibraries(&b);
335 ASSERT_EQ(1u, b_inherited.size());
336 EXPECT_EQ(&c, b_inherited[0].target());
337
338 // A should have B and C in its inherited libs.
339 const auto& a_inherited = resolved.GetInheritedLibraries(&a);
340 ASSERT_EQ(2u, a_inherited.size());
341 EXPECT_EQ(&b, a_inherited[0].target());
342 EXPECT_EQ(&c, a_inherited[1].target());
343 }
344
TEST(ResolvedTargetDataTest,NoActionDepPropgation)345 TEST(ResolvedTargetDataTest, NoActionDepPropgation) {
346 TestWithScope setup;
347 Err err;
348 ResolvedTargetData resolved;
349
350 // Create a dependency chain:
351 // A (exe) -> B (action) -> C (source_set)
352 {
353 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
354 TestTarget b(setup, "//foo:b", Target::ACTION);
355 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
356
357 a.private_deps().push_back(LabelTargetPair(&b));
358 b.private_deps().push_back(LabelTargetPair(&c));
359
360 ASSERT_TRUE(c.OnResolved(&err));
361 ASSERT_TRUE(b.OnResolved(&err));
362 ASSERT_TRUE(a.OnResolved(&err));
363
364 // The executable should not have inherited the source set across the
365 // action.
366 const auto& libs = resolved.GetInheritedLibraries(&a);
367 ASSERT_TRUE(libs.empty());
368 }
369 }
370
371 // Shared libraries should be inherited across public shared library
372 // boundaries.
TEST(ResolvedTargetDataTest,SharedInheritance)373 TEST(ResolvedTargetDataTest, SharedInheritance) {
374 TestWithScope setup;
375 Err err;
376
377 // Create two leaf shared libraries.
378 TestTarget pub(setup, "//foo:pub", Target::SHARED_LIBRARY);
379 ASSERT_TRUE(pub.OnResolved(&err));
380
381 TestTarget priv(setup, "//foo:priv", Target::SHARED_LIBRARY);
382 ASSERT_TRUE(priv.OnResolved(&err));
383
384 // Intermediate shared library with the leaf shared libraries as
385 // dependencies, one public, one private.
386 TestTarget inter(setup, "//foo:inter", Target::SHARED_LIBRARY);
387 inter.public_deps().push_back(LabelTargetPair(&pub));
388 inter.private_deps().push_back(LabelTargetPair(&priv));
389 ASSERT_TRUE(inter.OnResolved(&err));
390
391 // The intermediate shared library should have both "pub" and "priv" in its
392 // inherited libraries.
393 ResolvedTargetData resolved;
394 const auto& inter_inherited = resolved.GetInheritedLibraries(&inter);
395 ASSERT_EQ(2u, inter_inherited.size());
396 EXPECT_EQ(&pub, inter_inherited[0].target());
397 EXPECT_EQ(&priv, inter_inherited[1].target());
398
399 // Make a toplevel executable target depending on the intermediate one.
400 TestTarget exe(setup, "//foo:exe", Target::SHARED_LIBRARY);
401 exe.private_deps().push_back(LabelTargetPair(&inter));
402 ASSERT_TRUE(exe.OnResolved(&err));
403
404 // The exe's inherited libraries should be "inter" (because it depended
405 // directly on it) and "pub" (because inter depended publicly on it).
406 const auto& exe_inherited = resolved.GetInheritedLibraries(&exe);
407 ASSERT_EQ(2u, exe_inherited.size());
408 EXPECT_EQ(&inter, exe_inherited[0].target());
409 EXPECT_EQ(&pub, exe_inherited[1].target());
410 }
411