• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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