1 // Copyright 2022 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,LibInheritance)12 TEST(ResolvedTargetDataTest, LibInheritance) {
13 TestWithScope setup;
14 Err err;
15
16 ResolvedTargetData resolved;
17
18 const LibFile lib("foo");
19 const SourceDir libdir("/foo_dir/");
20
21 // Leaf target with ldflags set.
22 TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
23 z.config_values().libs().push_back(lib);
24 z.config_values().lib_dirs().push_back(libdir);
25 ASSERT_TRUE(z.OnResolved(&err));
26
27 // All lib[_dir]s should be set when target is resolved.
28 auto z_info = resolved.GetLibInfo(&z);
29 ASSERT_EQ(1u, z_info.all_libs.size());
30 EXPECT_EQ(lib, z_info.all_libs[0]);
31 ASSERT_EQ(1u, z_info.all_lib_dirs.size());
32 EXPECT_EQ(libdir, z_info.all_lib_dirs[0]);
33
34 // Shared library target should inherit the libs from the static library
35 // and its own. Its own flag should be before the inherited one.
36 const LibFile second_lib("bar");
37 const SourceDir second_libdir("/bar_dir/");
38 TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
39 shared.config_values().libs().push_back(second_lib);
40 shared.config_values().lib_dirs().push_back(second_libdir);
41 shared.private_deps().push_back(LabelTargetPair(&z));
42 ASSERT_TRUE(shared.OnResolved(&err));
43
44 const auto libinfo = resolved.GetLibInfo(&shared);
45 ASSERT_EQ(2u, libinfo.all_libs.size());
46 EXPECT_EQ(second_lib, libinfo.all_libs[0]);
47 EXPECT_EQ(lib, libinfo.all_libs[1]);
48 ASSERT_EQ(2u, libinfo.all_lib_dirs.size());
49 EXPECT_EQ(second_libdir, libinfo.all_lib_dirs[0]);
50 EXPECT_EQ(libdir, libinfo.all_lib_dirs[1]);
51
52 // Executable target shouldn't get either by depending on shared.
53 TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
54 exec.private_deps().push_back(LabelTargetPair(&shared));
55 ASSERT_TRUE(exec.OnResolved(&err));
56 auto exec_libinfo = resolved.GetLibInfo(&exec);
57 EXPECT_EQ(0u, exec_libinfo.all_libs.size());
58 EXPECT_EQ(0u, exec_libinfo.all_lib_dirs.size());
59 }
60
61 // Tests that framework[_dir]s are inherited across deps boundaries for static
62 // libraries but not executables.
TEST(ResolvedTargetDataTest,FrameworkInheritance)63 TEST(ResolvedTargetDataTest, FrameworkInheritance) {
64 TestWithScope setup;
65 Err err;
66
67 const std::string framework("Foo.framework");
68 const SourceDir frameworkdir("//out/foo/");
69
70 // Leaf target with ldflags set.
71 TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
72 z.config_values().frameworks().push_back(framework);
73 z.config_values().framework_dirs().push_back(frameworkdir);
74 ASSERT_TRUE(z.OnResolved(&err));
75
76 ResolvedTargetData resolved;
77
78 // All framework[_dir]s should be set when target is resolved.
79 auto info = resolved.GetFrameworkInfo(&z);
80 ASSERT_EQ(1u, info.all_frameworks.size());
81 EXPECT_EQ(framework, info.all_frameworks[0]);
82 ASSERT_EQ(1u, info.all_framework_dirs.size());
83 EXPECT_EQ(frameworkdir, info.all_framework_dirs[0]);
84
85 // Shared library target should inherit the libs from the static library
86 // and its own. Its own flag should be before the inherited one.
87 const std::string second_framework("Bar.framework");
88 const SourceDir second_frameworkdir("//out/bar/");
89 TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
90 shared.config_values().frameworks().push_back(second_framework);
91 shared.config_values().framework_dirs().push_back(second_frameworkdir);
92 shared.private_deps().push_back(LabelTargetPair(&z));
93 ASSERT_TRUE(shared.OnResolved(&err));
94
95 auto shared_info = resolved.GetFrameworkInfo(&shared);
96 ASSERT_EQ(2u, shared_info.all_frameworks.size());
97 EXPECT_EQ(second_framework, shared_info.all_frameworks[0]);
98 EXPECT_EQ(framework, shared_info.all_frameworks[1]);
99 ASSERT_EQ(2u, shared_info.all_framework_dirs.size());
100 EXPECT_EQ(second_frameworkdir, shared_info.all_framework_dirs[0]);
101 EXPECT_EQ(frameworkdir, shared_info.all_framework_dirs[1]);
102
103 // Executable target shouldn't get either by depending on shared.
104 TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
105 exec.private_deps().push_back(LabelTargetPair(&shared));
106 ASSERT_TRUE(exec.OnResolved(&err));
107 auto exec_info = resolved.GetFrameworkInfo(&exec);
108 EXPECT_EQ(0u, exec_info.all_frameworks.size());
109 EXPECT_EQ(0u, exec_info.all_framework_dirs.size());
110 }
111
TEST(ResolvedTargetDataTest,InheritLibs)112 TEST(ResolvedTargetDataTest, InheritLibs) {
113 TestWithScope setup;
114 Err err;
115
116 // Create a dependency chain:
117 // A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
118 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
119 TestTarget b(setup, "//foo:b", Target::SHARED_LIBRARY);
120 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
121 TestTarget d(setup, "//foo:d", Target::SOURCE_SET);
122 a.private_deps().push_back(LabelTargetPair(&b));
123 b.private_deps().push_back(LabelTargetPair(&c));
124 c.private_deps().push_back(LabelTargetPair(&d));
125
126 ASSERT_TRUE(d.OnResolved(&err));
127 ASSERT_TRUE(c.OnResolved(&err));
128 ASSERT_TRUE(b.OnResolved(&err));
129 ASSERT_TRUE(a.OnResolved(&err));
130
131 ResolvedTargetData resolved;
132
133 // C should have D in its inherited libs.
134 auto c_inherited_libs = resolved.inherited_libraries(&c);
135 ASSERT_EQ(1u, c_inherited_libs.size());
136 EXPECT_EQ(&d, c_inherited_libs[0].target());
137
138 // B should have C and D in its inherited libs.
139 auto b_inherited = resolved.inherited_libraries(&b);
140 ASSERT_EQ(2u, b_inherited.size());
141 EXPECT_EQ(&c, b_inherited[0].target());
142 EXPECT_EQ(&d, b_inherited[1].target());
143
144 // A should have B in its inherited libs, but not any others (the shared
145 // library will include the static library and source set).
146 auto a_inherited = resolved.inherited_libraries(&a);
147 ASSERT_EQ(1u, a_inherited.size());
148 EXPECT_EQ(&b, a_inherited[0].target());
149 }
150
TEST(ResolvedTargetData,NoActionDepPropgation)151 TEST(ResolvedTargetData, NoActionDepPropgation) {
152 TestWithScope setup;
153 Err err;
154 ResolvedTargetData resolved;
155 // Create a dependency chain:
156 // A (exe) -> B (action) -> C (source_set)
157 {
158 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
159 TestTarget b(setup, "//foo:b", Target::ACTION);
160 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
161
162 a.private_deps().push_back(LabelTargetPair(&b));
163 b.private_deps().push_back(LabelTargetPair(&c));
164
165 ASSERT_TRUE(c.OnResolved(&err));
166 ASSERT_TRUE(b.OnResolved(&err));
167 ASSERT_TRUE(a.OnResolved(&err));
168
169 // The executable should not have inherited the source set across the
170 // action.
171 ASSERT_TRUE(resolved.inherited_libraries(&a).empty());
172 }
173 }
174
TEST(ResolvedTargetDataTest,InheritCompleteStaticLib)175 TEST(ResolvedTargetDataTest, InheritCompleteStaticLib) {
176 TestWithScope setup;
177 Err err;
178
179 ResolvedTargetData resolved;
180
181 // Create a dependency chain:
182 // A (executable) -> B (complete static lib) -> C (source set)
183 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
184 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
185 b.set_complete_static_lib(true);
186
187 const LibFile lib("foo");
188 const SourceDir lib_dir("/foo_dir/");
189 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
190 c.config_values().libs().push_back(lib);
191 c.config_values().lib_dirs().push_back(lib_dir);
192
193 a.public_deps().push_back(LabelTargetPair(&b));
194 b.public_deps().push_back(LabelTargetPair(&c));
195
196 ASSERT_TRUE(c.OnResolved(&err));
197 ASSERT_TRUE(b.OnResolved(&err));
198 ASSERT_TRUE(a.OnResolved(&err));
199
200 // B should have C in its inherited libs.
201 auto b_inherited = resolved.inherited_libraries(&b);
202 ASSERT_EQ(1u, b_inherited.size());
203 EXPECT_EQ(&c, b_inherited[0].target());
204
205 // A should have B in its inherited libs, but not any others (the complete
206 // static library will include the source set).
207 auto a_inherited = resolved.inherited_libraries(&a);
208 ASSERT_EQ(1u, a_inherited.size());
209 EXPECT_EQ(&b, a_inherited[0].target());
210
211 // A should inherit the libs and lib_dirs from the C.
212 auto a_info = resolved.GetLibInfo(&a);
213 ASSERT_EQ(1u, a_info.all_libs.size());
214 EXPECT_EQ(lib, a_info.all_libs[0]);
215 ASSERT_EQ(1u, a_info.all_lib_dirs.size());
216 EXPECT_EQ(lib_dir, a_info.all_lib_dirs[0]);
217 }
218
TEST(ResolvedTargetDataTest,InheritCompleteStaticLibStaticLibDeps)219 TEST(ResolvedTargetDataTest, InheritCompleteStaticLibStaticLibDeps) {
220 TestWithScope setup;
221 Err err;
222
223 // Create a dependency chain:
224 // A (executable) -> B (complete static lib) -> C (static lib)
225 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
226 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
227 b.set_complete_static_lib(true);
228 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
229 a.public_deps().push_back(LabelTargetPair(&b));
230 b.public_deps().push_back(LabelTargetPair(&c));
231
232 ASSERT_TRUE(c.OnResolved(&err));
233 ASSERT_TRUE(b.OnResolved(&err));
234 ASSERT_TRUE(a.OnResolved(&err));
235
236 ResolvedTargetData resolved;
237
238 // B should have C in its inherited libs.
239 auto b_inherited = resolved.inherited_libraries(&b);
240 ASSERT_EQ(1u, b_inherited.size());
241 EXPECT_EQ(&c, b_inherited[0].target());
242
243 // A should have B in its inherited libs, but not any others (the complete
244 // static library will include the static library).
245 auto a_inherited = resolved.inherited_libraries(&a);
246 ASSERT_EQ(1u, a_inherited.size());
247 EXPECT_EQ(&b, a_inherited[0].target());
248 }
249
TEST(ResolvedTargetDataTest,InheritCompleteStaticLibInheritedCompleteStaticLibDeps)250 TEST(ResolvedTargetDataTest,
251 InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
252 TestWithScope setup;
253 Err err;
254
255 // Create a dependency chain:
256 // A (executable) -> B (complete static lib) -> C (complete static lib)
257 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
258 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
259 b.set_complete_static_lib(true);
260 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
261 c.set_complete_static_lib(true);
262
263 a.private_deps().push_back(LabelTargetPair(&b));
264 b.private_deps().push_back(LabelTargetPair(&c));
265
266 ASSERT_TRUE(c.OnResolved(&err));
267 ASSERT_TRUE(b.OnResolved(&err));
268 ASSERT_TRUE(a.OnResolved(&err));
269
270 ResolvedTargetData resolved;
271
272 // B should have C in its inherited libs.
273 auto b_inherited = resolved.inherited_libraries(&b);
274 ASSERT_EQ(1u, b_inherited.size());
275 EXPECT_EQ(&c, b_inherited[0].target());
276
277 // A should have B and C in its inherited libs.
278 auto a_inherited = resolved.inherited_libraries(&a);
279 ASSERT_EQ(2u, a_inherited.size());
280 EXPECT_EQ(&b, a_inherited[0].target());
281 EXPECT_EQ(&c, a_inherited[1].target());
282 }
283
TEST(ResolvedTargetDataTest,NoActionDepPropgation)284 TEST(ResolvedTargetDataTest, NoActionDepPropgation) {
285 TestWithScope setup;
286 Err err;
287 ResolvedTargetData resolved;
288
289 // Create a dependency chain:
290 // A (exe) -> B (action) -> C (source_set)
291 {
292 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
293 TestTarget b(setup, "//foo:b", Target::ACTION);
294 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
295
296 a.private_deps().push_back(LabelTargetPair(&b));
297 b.private_deps().push_back(LabelTargetPair(&c));
298
299 ASSERT_TRUE(c.OnResolved(&err));
300 ASSERT_TRUE(b.OnResolved(&err));
301 ASSERT_TRUE(a.OnResolved(&err));
302
303 // The executable should not have inherited the source set across the
304 // action.
305 auto libs = resolved.inherited_libraries(&a);
306 ASSERT_TRUE(libs.empty());
307 }
308 }
309