1 // Copyright (c) 2013 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/target.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "gn/build_settings.h"
11 #include "gn/config.h"
12 #include "gn/scheduler.h"
13 #include "gn/settings.h"
14 #include "gn/test_with_scheduler.h"
15 #include "gn/test_with_scope.h"
16 #include "gn/toolchain.h"
17 #include "util/test/test.h"
18
19 namespace {
20
21 // Asserts that the current global scheduler has a single unknown generated
22 // file with the given name from the given target.
AssertSchedulerHasOneUnknownFileMatching(const Target * target,const SourceFile & file)23 void AssertSchedulerHasOneUnknownFileMatching(const Target* target,
24 const SourceFile& file) {
25 auto unknown = g_scheduler->GetUnknownGeneratedInputs();
26 ASSERT_EQ(1u, unknown.size()); // Should be one unknown file.
27 auto found = unknown.find(file);
28 ASSERT_TRUE(found != unknown.end()) << file.value();
29 EXPECT_TRUE(target == found->second)
30 << "Target doesn't match. Expected\n "
31 << target->label().GetUserVisibleName(false) << "\nBut got\n "
32 << found->second->label().GetUserVisibleName(false);
33 }
34
35 } // namespace
36
37 using TargetTest = TestWithScheduler;
38
39 // Tests that lib[_dir]s are inherited across deps boundaries for static
40 // libraries but not executables.
TEST_F(TargetTest,LibInheritance)41 TEST_F(TargetTest, LibInheritance) {
42 TestWithScope setup;
43 Err err;
44
45 const LibFile lib("foo");
46 const SourceDir libdir("/foo_dir/");
47
48 // Leaf target with ldflags set.
49 TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
50 z.config_values().libs().push_back(lib);
51 z.config_values().lib_dirs().push_back(libdir);
52 ASSERT_TRUE(z.OnResolved(&err));
53
54 // All lib[_dir]s should be set when target is resolved.
55 ASSERT_EQ(1u, z.all_libs().size());
56 EXPECT_EQ(lib, z.all_libs()[0]);
57 ASSERT_EQ(1u, z.all_lib_dirs().size());
58 EXPECT_EQ(libdir, z.all_lib_dirs()[0]);
59
60 // Shared library target should inherit the libs from the static library
61 // and its own. Its own flag should be before the inherited one.
62 const LibFile second_lib("bar");
63 const SourceDir second_libdir("/bar_dir/");
64 TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
65 shared.config_values().libs().push_back(second_lib);
66 shared.config_values().lib_dirs().push_back(second_libdir);
67 shared.private_deps().push_back(LabelTargetPair(&z));
68 ASSERT_TRUE(shared.OnResolved(&err));
69
70 ASSERT_EQ(2u, shared.all_libs().size());
71 EXPECT_EQ(second_lib, shared.all_libs()[0]);
72 EXPECT_EQ(lib, shared.all_libs()[1]);
73 ASSERT_EQ(2u, shared.all_lib_dirs().size());
74 EXPECT_EQ(second_libdir, shared.all_lib_dirs()[0]);
75 EXPECT_EQ(libdir, shared.all_lib_dirs()[1]);
76
77 // Executable target shouldn't get either by depending on shared.
78 TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
79 exec.private_deps().push_back(LabelTargetPair(&shared));
80 ASSERT_TRUE(exec.OnResolved(&err));
81 EXPECT_EQ(0u, exec.all_libs().size());
82 EXPECT_EQ(0u, exec.all_lib_dirs().size());
83 }
84
85 // Tests that framework[_dir]s are inherited across deps boundaries for static
86 // libraries but not executables.
TEST_F(TargetTest,FrameworkInheritance)87 TEST_F(TargetTest, FrameworkInheritance) {
88 TestWithScope setup;
89 Err err;
90
91 const std::string framework("Foo.framework");
92 const SourceDir frameworkdir("//out/foo/");
93
94 // Leaf target with ldflags set.
95 TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
96 z.config_values().frameworks().push_back(framework);
97 z.config_values().framework_dirs().push_back(frameworkdir);
98 ASSERT_TRUE(z.OnResolved(&err));
99
100 // All framework[_dir]s should be set when target is resolved.
101 ASSERT_EQ(1u, z.all_frameworks().size());
102 EXPECT_EQ(framework, z.all_frameworks()[0]);
103 ASSERT_EQ(1u, z.all_framework_dirs().size());
104 EXPECT_EQ(frameworkdir, z.all_framework_dirs()[0]);
105
106 // Shared library target should inherit the libs from the static library
107 // and its own. Its own flag should be before the inherited one.
108 const std::string second_framework("Bar.framework");
109 const SourceDir second_frameworkdir("//out/bar/");
110 TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
111 shared.config_values().frameworks().push_back(second_framework);
112 shared.config_values().framework_dirs().push_back(second_frameworkdir);
113 shared.private_deps().push_back(LabelTargetPair(&z));
114 ASSERT_TRUE(shared.OnResolved(&err));
115
116 ASSERT_EQ(2u, shared.all_frameworks().size());
117 EXPECT_EQ(second_framework, shared.all_frameworks()[0]);
118 EXPECT_EQ(framework, shared.all_frameworks()[1]);
119 ASSERT_EQ(2u, shared.all_framework_dirs().size());
120 EXPECT_EQ(second_frameworkdir, shared.all_framework_dirs()[0]);
121 EXPECT_EQ(frameworkdir, shared.all_framework_dirs()[1]);
122
123 // Executable target shouldn't get either by depending on shared.
124 TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
125 exec.private_deps().push_back(LabelTargetPair(&shared));
126 ASSERT_TRUE(exec.OnResolved(&err));
127 EXPECT_EQ(0u, exec.all_frameworks().size());
128 EXPECT_EQ(0u, exec.all_framework_dirs().size());
129 }
130
131 // Test all_dependent_configs and public_config inheritance.
TEST_F(TargetTest,DependentConfigs)132 TEST_F(TargetTest, DependentConfigs) {
133 TestWithScope setup;
134 Err err;
135
136 // Set up a dependency chain of a -> b -> c
137 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
138 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
139 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
140 a.private_deps().push_back(LabelTargetPair(&b));
141 b.private_deps().push_back(LabelTargetPair(&c));
142
143 // Normal non-inherited config.
144 Config config(setup.settings(), Label(SourceDir("//foo/"), "config"));
145 config.visibility().SetPublic();
146 ASSERT_TRUE(config.OnResolved(&err));
147 c.configs().push_back(LabelConfigPair(&config));
148
149 // All dependent config.
150 Config all(setup.settings(), Label(SourceDir("//foo/"), "all"));
151 all.visibility().SetPublic();
152 ASSERT_TRUE(all.OnResolved(&err));
153 c.all_dependent_configs().push_back(LabelConfigPair(&all));
154
155 // Direct dependent config.
156 Config direct(setup.settings(), Label(SourceDir("//foo/"), "direct"));
157 direct.visibility().SetPublic();
158 ASSERT_TRUE(direct.OnResolved(&err));
159 c.public_configs().push_back(LabelConfigPair(&direct));
160
161 ASSERT_TRUE(c.OnResolved(&err));
162 ASSERT_TRUE(b.OnResolved(&err));
163 ASSERT_TRUE(a.OnResolved(&err));
164
165 // B should have gotten both dependent configs from C.
166 ASSERT_EQ(2u, b.configs().size());
167 EXPECT_EQ(&all, b.configs()[0].ptr);
168 EXPECT_EQ(&direct, b.configs()[1].ptr);
169 ASSERT_EQ(1u, b.all_dependent_configs().size());
170 EXPECT_EQ(&all, b.all_dependent_configs()[0].ptr);
171
172 // A should have just gotten the "all" dependent config from C.
173 ASSERT_EQ(1u, a.configs().size());
174 EXPECT_EQ(&all, a.configs()[0].ptr);
175 EXPECT_EQ(&all, a.all_dependent_configs()[0].ptr);
176
177 // Making an an alternate A and B with B forwarding the direct dependents.
178 TestTarget a_fwd(setup, "//foo:a_fwd", Target::EXECUTABLE);
179 TestTarget b_fwd(setup, "//foo:b_fwd", Target::STATIC_LIBRARY);
180 a_fwd.private_deps().push_back(LabelTargetPair(&b_fwd));
181 b_fwd.private_deps().push_back(LabelTargetPair(&c));
182
183 ASSERT_TRUE(b_fwd.OnResolved(&err));
184 ASSERT_TRUE(a_fwd.OnResolved(&err));
185
186 // A_fwd should now have both configs.
187 ASSERT_EQ(1u, a_fwd.configs().size());
188 EXPECT_EQ(&all, a_fwd.configs()[0].ptr);
189 ASSERT_EQ(1u, a_fwd.all_dependent_configs().size());
190 EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr);
191 }
192
193 // Tests that dependent configs don't propagate between toolchains.
TEST_F(TargetTest,NoDependentConfigsBetweenToolchains)194 TEST_F(TargetTest, NoDependentConfigsBetweenToolchains) {
195 TestWithScope setup;
196 Err err;
197
198 // Create another toolchain.
199 Toolchain other_toolchain(setup.settings(),
200 Label(SourceDir("//other/"), "toolchain"));
201 TestWithScope::SetupToolchain(&other_toolchain);
202
203 // Set up a dependency chain of |a| -> |b| -> |c| where |a| has a different
204 // toolchain.
205 Target a(setup.settings(),
206 Label(SourceDir("//foo/"), "a", other_toolchain.label().dir(),
207 other_toolchain.label().name()));
208 a.set_output_type(Target::EXECUTABLE);
209 EXPECT_TRUE(a.SetToolchain(&other_toolchain, &err));
210 TestTarget b(setup, "//foo:b", Target::EXECUTABLE);
211 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
212 a.private_deps().push_back(LabelTargetPair(&b));
213 b.private_deps().push_back(LabelTargetPair(&c));
214
215 // All dependent config.
216 Config all_dependent(setup.settings(), Label(SourceDir("//foo/"), "all"));
217 all_dependent.visibility().SetPublic();
218 ASSERT_TRUE(all_dependent.OnResolved(&err));
219 c.all_dependent_configs().push_back(LabelConfigPair(&all_dependent));
220
221 // Public config.
222 Config public_config(setup.settings(), Label(SourceDir("//foo/"), "public"));
223 public_config.visibility().SetPublic();
224 ASSERT_TRUE(public_config.OnResolved(&err));
225 c.public_configs().push_back(LabelConfigPair(&public_config));
226
227 // Another public config.
228 Config public_config2(setup.settings(),
229 Label(SourceDir("//foo/"), "public2"));
230 public_config2.visibility().SetPublic();
231 ASSERT_TRUE(public_config2.OnResolved(&err));
232 b.public_configs().push_back(LabelConfigPair(&public_config2));
233
234 ASSERT_TRUE(c.OnResolved(&err));
235 ASSERT_TRUE(b.OnResolved(&err));
236 ASSERT_TRUE(a.OnResolved(&err));
237
238 // B should have gotten the configs from C.
239 ASSERT_EQ(3u, b.configs().size());
240 EXPECT_EQ(&public_config2, b.configs()[0].ptr);
241 EXPECT_EQ(&all_dependent, b.configs()[1].ptr);
242 EXPECT_EQ(&public_config, b.configs()[2].ptr);
243 ASSERT_EQ(1u, b.all_dependent_configs().size());
244 EXPECT_EQ(&all_dependent, b.all_dependent_configs()[0].ptr);
245
246 // A should not have gotten any configs from B or C.
247 ASSERT_EQ(0u, a.configs().size());
248 ASSERT_EQ(0u, a.all_dependent_configs().size());
249 }
250
251 // Tests that dependent configs propagate between toolchains if
252 // propagates_configs is set.
TEST_F(TargetTest,DependentConfigsBetweenToolchainsWhenSet)253 TEST_F(TargetTest, DependentConfigsBetweenToolchainsWhenSet) {
254 TestWithScope setup;
255 Err err;
256
257 // Create another toolchain.
258 Toolchain other_toolchain(setup.settings(),
259 Label(SourceDir("//other/"), "toolchain"));
260 TestWithScope::SetupToolchain(&other_toolchain);
261 other_toolchain.set_propagates_configs(true);
262
263 // Set up a dependency chain of |a| -> |b| where |b| has a different
264 // toolchain (with propagate_configs set).
265 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
266 Target b(setup.settings(),
267 Label(SourceDir("//foo/"), "b", other_toolchain.label().dir(),
268 other_toolchain.label().name()));
269 b.visibility().SetPublic();
270 b.set_output_type(Target::SHARED_LIBRARY);
271 EXPECT_TRUE(b.SetToolchain(&other_toolchain, &err));
272 a.private_deps().push_back(LabelTargetPair(&b));
273
274 // All dependent config.
275 Config all_dependent(setup.settings(), Label(SourceDir("//foo/"), "all"));
276 all_dependent.visibility().SetPublic();
277 ASSERT_TRUE(all_dependent.OnResolved(&err));
278 b.all_dependent_configs().push_back(LabelConfigPair(&all_dependent));
279
280 // Public config.
281 Config public_config(setup.settings(), Label(SourceDir("//foo/"), "public"));
282 public_config.visibility().SetPublic();
283 ASSERT_TRUE(public_config.OnResolved(&err));
284 b.public_configs().push_back(LabelConfigPair(&public_config));
285
286 ASSERT_TRUE(b.OnResolved(&err));
287 ASSERT_TRUE(a.OnResolved(&err));
288
289 // A should have gotten the configs from B.
290 ASSERT_EQ(2u, a.configs().size());
291 EXPECT_EQ(&all_dependent, a.configs()[0].ptr);
292 EXPECT_EQ(&public_config, a.configs()[1].ptr);
293 ASSERT_EQ(1u, a.all_dependent_configs().size());
294 EXPECT_EQ(&all_dependent, a.all_dependent_configs()[0].ptr);
295 }
296
TEST_F(TargetTest,InheritLibs)297 TEST_F(TargetTest, InheritLibs) {
298 TestWithScope setup;
299 Err err;
300
301 // Create a dependency chain:
302 // A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
303 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
304 TestTarget b(setup, "//foo:b", Target::SHARED_LIBRARY);
305 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
306 TestTarget d(setup, "//foo:d", Target::SOURCE_SET);
307 a.private_deps().push_back(LabelTargetPair(&b));
308 b.private_deps().push_back(LabelTargetPair(&c));
309 c.private_deps().push_back(LabelTargetPair(&d));
310
311 ASSERT_TRUE(d.OnResolved(&err));
312 ASSERT_TRUE(c.OnResolved(&err));
313 ASSERT_TRUE(b.OnResolved(&err));
314 ASSERT_TRUE(a.OnResolved(&err));
315
316 // C should have D in its inherited libs.
317 std::vector<const Target*> c_inherited = c.inherited_libraries().GetOrdered();
318 ASSERT_EQ(1u, c_inherited.size());
319 EXPECT_EQ(&d, c_inherited[0]);
320
321 // B should have C and D in its inherited libs.
322 std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
323 ASSERT_EQ(2u, b_inherited.size());
324 EXPECT_EQ(&c, b_inherited[0]);
325 EXPECT_EQ(&d, b_inherited[1]);
326
327 // A should have B in its inherited libs, but not any others (the shared
328 // library will include the static library and source set).
329 std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
330 ASSERT_EQ(1u, a_inherited.size());
331 EXPECT_EQ(&b, a_inherited[0]);
332 }
333
TEST_F(TargetTest,InheritCompleteStaticLib)334 TEST_F(TargetTest, InheritCompleteStaticLib) {
335 TestWithScope setup;
336 Err err;
337
338 // Create a dependency chain:
339 // A (executable) -> B (complete static lib) -> C (source set)
340 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
341 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
342 b.set_complete_static_lib(true);
343
344 const LibFile lib("foo");
345 const SourceDir lib_dir("/foo_dir/");
346 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
347 c.config_values().libs().push_back(lib);
348 c.config_values().lib_dirs().push_back(lib_dir);
349
350 a.public_deps().push_back(LabelTargetPair(&b));
351 b.public_deps().push_back(LabelTargetPair(&c));
352
353 ASSERT_TRUE(c.OnResolved(&err));
354 ASSERT_TRUE(b.OnResolved(&err));
355 ASSERT_TRUE(a.OnResolved(&err));
356
357 // B should have C in its inherited libs.
358 std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
359 ASSERT_EQ(1u, b_inherited.size());
360 EXPECT_EQ(&c, b_inherited[0]);
361
362 // A should have B in its inherited libs, but not any others (the complete
363 // static library will include the source set).
364 std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
365 ASSERT_EQ(1u, a_inherited.size());
366 EXPECT_EQ(&b, a_inherited[0]);
367
368 // A should inherit the libs and lib_dirs from the C.
369 ASSERT_EQ(1u, a.all_libs().size());
370 EXPECT_EQ(lib, a.all_libs()[0]);
371 ASSERT_EQ(1u, a.all_lib_dirs().size());
372 EXPECT_EQ(lib_dir, a.all_lib_dirs()[0]);
373 }
374
TEST_F(TargetTest,InheritCompleteStaticLibStaticLibDeps)375 TEST_F(TargetTest, InheritCompleteStaticLibStaticLibDeps) {
376 TestWithScope setup;
377 Err err;
378
379 // Create a dependency chain:
380 // A (executable) -> B (complete static lib) -> C (static lib)
381 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
382 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
383 b.set_complete_static_lib(true);
384 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
385 a.public_deps().push_back(LabelTargetPair(&b));
386 b.public_deps().push_back(LabelTargetPair(&c));
387
388 ASSERT_TRUE(c.OnResolved(&err));
389 ASSERT_TRUE(b.OnResolved(&err));
390 ASSERT_TRUE(a.OnResolved(&err));
391
392 // B should have C in its inherited libs.
393 std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
394 ASSERT_EQ(1u, b_inherited.size());
395 EXPECT_EQ(&c, b_inherited[0]);
396
397 // A should have B in its inherited libs, but not any others (the complete
398 // static library will include the static library).
399 std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
400 ASSERT_EQ(1u, a_inherited.size());
401 EXPECT_EQ(&b, a_inherited[0]);
402 }
403
TEST_F(TargetTest,InheritCompleteStaticLibInheritedCompleteStaticLibDeps)404 TEST_F(TargetTest, InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
405 TestWithScope setup;
406 Err err;
407
408 // Create a dependency chain:
409 // A (executable) -> B (complete static lib) -> C (complete static lib)
410 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
411 TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
412 b.set_complete_static_lib(true);
413 TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
414 c.set_complete_static_lib(true);
415
416 a.private_deps().push_back(LabelTargetPair(&b));
417 b.private_deps().push_back(LabelTargetPair(&c));
418
419 ASSERT_TRUE(c.OnResolved(&err));
420 ASSERT_TRUE(b.OnResolved(&err));
421 ASSERT_TRUE(a.OnResolved(&err));
422
423 // B should have C in its inherited libs.
424 std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
425 ASSERT_EQ(1u, b_inherited.size());
426 EXPECT_EQ(&c, b_inherited[0]);
427
428 // A should have B and C in its inherited libs.
429 std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
430 ASSERT_EQ(2u, a_inherited.size());
431 EXPECT_EQ(&b, a_inherited[0]);
432 EXPECT_EQ(&c, a_inherited[1]);
433 }
434
TEST_F(TargetTest,NoActionDepPropgation)435 TEST_F(TargetTest, NoActionDepPropgation) {
436 TestWithScope setup;
437 Err err;
438
439 // Create a dependency chain:
440 // A (exe) -> B (action) -> C (source_set)
441 {
442 TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
443 TestTarget b(setup, "//foo:b", Target::ACTION);
444 TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
445
446 a.private_deps().push_back(LabelTargetPair(&b));
447 b.private_deps().push_back(LabelTargetPair(&c));
448
449 ASSERT_TRUE(c.OnResolved(&err));
450 ASSERT_TRUE(b.OnResolved(&err));
451 ASSERT_TRUE(a.OnResolved(&err));
452
453 // The executable should not have inherited the source set across the
454 // action.
455 std::vector<const Target*> libs = a.inherited_libraries().GetOrdered();
456 ASSERT_TRUE(libs.empty());
457 }
458 }
459
TEST_F(TargetTest,GetComputedOutputName)460 TEST_F(TargetTest, GetComputedOutputName) {
461 TestWithScope setup;
462 Err err;
463
464 // Basic target with no prefix (executable type tool in the TestWithScope has
465 // no prefix) or output name.
466 TestTarget basic(setup, "//foo:bar", Target::EXECUTABLE);
467 ASSERT_TRUE(basic.OnResolved(&err));
468 EXPECT_EQ("bar", basic.GetComputedOutputName());
469
470 // Target with no prefix but an output name.
471 TestTarget with_name(setup, "//foo:bar", Target::EXECUTABLE);
472 with_name.set_output_name("myoutput");
473 ASSERT_TRUE(with_name.OnResolved(&err));
474 EXPECT_EQ("myoutput", with_name.GetComputedOutputName());
475
476 // Target with a "lib" prefix (the static library tool in the TestWithScope
477 // should specify a "lib" output prefix).
478 TestTarget with_prefix(setup, "//foo:bar", Target::STATIC_LIBRARY);
479 ASSERT_TRUE(with_prefix.OnResolved(&err));
480 EXPECT_EQ("libbar", with_prefix.GetComputedOutputName());
481
482 // Target with a "lib" prefix that already has it applied. The prefix should
483 // not duplicate something already in the target name.
484 TestTarget dup_prefix(setup, "//foo:bar", Target::STATIC_LIBRARY);
485 dup_prefix.set_output_name("libbar");
486 ASSERT_TRUE(dup_prefix.OnResolved(&err));
487 EXPECT_EQ("libbar", dup_prefix.GetComputedOutputName());
488
489 // Target with an output prefix override should not have a prefix.
490 TestTarget override_prefix(setup, "//foo:bar", Target::SHARED_LIBRARY);
491 override_prefix.set_output_prefix_override(true);
492 ASSERT_TRUE(dup_prefix.OnResolved(&err));
493 EXPECT_EQ("bar", override_prefix.GetComputedOutputName());
494 }
495
496 // Test visibility failure case.
TEST_F(TargetTest,VisibilityFails)497 TEST_F(TargetTest, VisibilityFails) {
498 TestWithScope setup;
499 Err err;
500
501 TestTarget b(setup, "//private:b", Target::STATIC_LIBRARY);
502 b.visibility().SetPrivate(b.label().dir());
503 ASSERT_TRUE(b.OnResolved(&err));
504
505 // Make a target depending on "b". The dependency must have an origin to mark
506 // it as user-set so we check visibility. This check should fail.
507 TestTarget a(setup, "//app:a", Target::EXECUTABLE);
508 a.private_deps().push_back(LabelTargetPair(&b));
509 IdentifierNode origin; // Dummy origin.
510 a.private_deps()[0].origin = &origin;
511 ASSERT_FALSE(a.OnResolved(&err));
512 }
513
514 // Test config visibility failure cases.
TEST_F(TargetTest,VisibilityConfigFails)515 TEST_F(TargetTest, VisibilityConfigFails) {
516 TestWithScope setup;
517 Err err;
518
519 Label config_label(SourceDir("//a/"), "config");
520 Config config(setup.settings(), config_label);
521 config.visibility().SetPrivate(config.label().dir());
522 ASSERT_TRUE(config.OnResolved(&err));
523
524 // Make a target using configs. This should fail.
525 TestTarget a(setup, "//app:a", Target::EXECUTABLE);
526 a.configs().push_back(LabelConfigPair(&config));
527 ASSERT_FALSE(a.OnResolved(&err));
528
529 // A target using public_configs should also fail.
530 TestTarget b(setup, "//app:b", Target::EXECUTABLE);
531 b.public_configs().push_back(LabelConfigPair(&config));
532 ASSERT_FALSE(b.OnResolved(&err));
533
534 // A target using all_dependent_configs should fail as well.
535 TestTarget c(setup, "//app:c", Target::EXECUTABLE);
536 c.all_dependent_configs().push_back(LabelConfigPair(&config));
537 ASSERT_FALSE(c.OnResolved(&err));
538 }
539
540 // Test Config -> Group -> A where the config is group is visible from A but
541 // the config isn't, and the config is visible from the group.
TEST_F(TargetTest,VisibilityConfigGroup)542 TEST_F(TargetTest, VisibilityConfigGroup) {
543 TestWithScope setup;
544 Err err;
545
546 Label config_label(SourceDir("//a/"), "config");
547 Config config(setup.settings(), config_label);
548 config.visibility().SetPrivate(config.label().dir());
549 ASSERT_TRUE(config.OnResolved(&err));
550
551 // Make a target using the config in the same directory.
552 TestTarget a(setup, "//a:a", Target::GROUP);
553 a.public_configs().push_back(LabelConfigPair(&config));
554 ASSERT_TRUE(a.OnResolved(&err));
555
556 // A target depending on a should be okay.
557 TestTarget b(setup, "//app:b", Target::EXECUTABLE);
558 b.private_deps().push_back(LabelTargetPair(&a));
559 ASSERT_TRUE(b.OnResolved(&err));
560 }
561
562 // Test visibility with a single data_dep.
TEST_F(TargetTest,VisibilityDatadeps)563 TEST_F(TargetTest, VisibilityDatadeps) {
564 TestWithScope setup;
565 Err err;
566
567 TestTarget b(setup, "//public:b", Target::STATIC_LIBRARY);
568 ASSERT_TRUE(b.OnResolved(&err));
569
570 // Make a target depending on "b". The dependency must have an origin to mark
571 // it as user-set so we check visibility. This check should fail.
572 TestTarget a(setup, "//app:a", Target::EXECUTABLE);
573 a.data_deps().push_back(LabelTargetPair(&b));
574 IdentifierNode origin; // Dummy origin.
575 a.data_deps()[0].origin = &origin;
576 ASSERT_TRUE(a.OnResolved(&err)) << err.help_text();
577 }
578
579 // Tests that A -> Group -> B where the group is visible from A but B isn't,
580 // passes visibility even though the group's deps get expanded into A.
TEST_F(TargetTest,VisibilityGroup)581 TEST_F(TargetTest, VisibilityGroup) {
582 TestWithScope setup;
583 Err err;
584
585 IdentifierNode origin; // Dummy origin.
586
587 // B has private visibility. This lets the group see it since the group is in
588 // the same directory.
589 TestTarget b(setup, "//private:b", Target::STATIC_LIBRARY);
590 b.visibility().SetPrivate(b.label().dir());
591 ASSERT_TRUE(b.OnResolved(&err));
592
593 // The group has public visibility and depends on b.
594 TestTarget g(setup, "//public:g", Target::GROUP);
595 g.private_deps().push_back(LabelTargetPair(&b));
596 g.private_deps()[0].origin = &origin;
597 ASSERT_TRUE(b.OnResolved(&err));
598
599 // Make a target depending on "g". This should succeed.
600 TestTarget a(setup, "//app:a", Target::EXECUTABLE);
601 a.private_deps().push_back(LabelTargetPair(&g));
602 a.private_deps()[0].origin = &origin;
603 ASSERT_TRUE(a.OnResolved(&err));
604 }
605
606 // Verifies that only testonly targets can depend on other testonly targets.
607 // Many of the above dependency checking cases covered the non-testonly
608 // case.
TEST_F(TargetTest,Testonly)609 TEST_F(TargetTest, Testonly) {
610 TestWithScope setup;
611 Err err;
612
613 // "testlib" is a test-only library.
614 TestTarget testlib(setup, "//test:testlib", Target::STATIC_LIBRARY);
615 testlib.set_testonly(true);
616 ASSERT_TRUE(testlib.OnResolved(&err));
617
618 // "test" is a test-only executable depending on testlib, this is OK.
619 TestTarget test(setup, "//test:test", Target::EXECUTABLE);
620 test.set_testonly(true);
621 test.private_deps().push_back(LabelTargetPair(&testlib));
622 ASSERT_TRUE(test.OnResolved(&err));
623
624 // "product" is a non-test depending on testlib. This should fail.
625 TestTarget product(setup, "//app:product", Target::EXECUTABLE);
626 product.set_testonly(false);
627 product.private_deps().push_back(LabelTargetPair(&testlib));
628 ASSERT_FALSE(product.OnResolved(&err));
629 }
630
631 // Configs can be testonly too.
632 // Repeat the testonly test with a config.
TEST_F(TargetTest,TestonlyConfig)633 TEST_F(TargetTest, TestonlyConfig) {
634 TestWithScope setup;
635 Err err;
636
637 // "testconfig" is a test-only config.
638 Config testconfig(setup.settings(), Label(SourceDir("//test/"), "config"));
639 testconfig.set_testonly(true);
640 testconfig.visibility().SetPublic();
641 ASSERT_TRUE(testconfig.OnResolved(&err));
642
643 // "test" is a test-only executable that uses testconfig, this is OK.
644 TestTarget test(setup, "//test:test", Target::EXECUTABLE);
645 test.set_testonly(true);
646 test.configs().push_back(LabelConfigPair(&testconfig));
647 ASSERT_TRUE(test.OnResolved(&err));
648
649 // "product" is a non-test that uses testconfig. This should fail.
650 TestTarget product(setup, "//app:product", Target::EXECUTABLE);
651 product.set_testonly(false);
652 product.configs().push_back(LabelConfigPair(&testconfig));
653 ASSERT_FALSE(product.OnResolved(&err));
654 }
655
TEST_F(TargetTest,PublicConfigs)656 TEST_F(TargetTest, PublicConfigs) {
657 TestWithScope setup;
658 Err err;
659
660 Label pub_config_label(SourceDir("//a/"), "pubconfig");
661 Config pub_config(setup.settings(), pub_config_label);
662 pub_config.visibility().SetPublic();
663 LibFile lib_name("testlib");
664 pub_config.own_values().libs().push_back(lib_name);
665 ASSERT_TRUE(pub_config.OnResolved(&err));
666
667 // This is the destination target that has a public config.
668 TestTarget dest(setup, "//a:a", Target::SOURCE_SET);
669 dest.public_configs().push_back(LabelConfigPair(&pub_config));
670 ASSERT_TRUE(dest.OnResolved(&err));
671
672 // This target has a public dependency on dest.
673 TestTarget pub(setup, "//a:pub", Target::SOURCE_SET);
674 pub.public_deps().push_back(LabelTargetPair(&dest));
675 ASSERT_TRUE(pub.OnResolved(&err));
676
677 // Depending on the target with the public dependency should forward dest's
678 // to the current target.
679 TestTarget dep_on_pub(setup, "//a:dop", Target::SOURCE_SET);
680 dep_on_pub.private_deps().push_back(LabelTargetPair(&pub));
681 ASSERT_TRUE(dep_on_pub.OnResolved(&err));
682 ASSERT_EQ(1u, dep_on_pub.configs().size());
683 EXPECT_EQ(&pub_config, dep_on_pub.configs()[0].ptr);
684
685 // Libs have special handling, check that they were forwarded from the
686 // public config to all_libs.
687 ASSERT_EQ(1u, dep_on_pub.all_libs().size());
688 ASSERT_EQ(lib_name, dep_on_pub.all_libs()[0]);
689
690 // This target has a private dependency on dest for forwards configs.
691 TestTarget forward(setup, "//a:f", Target::SOURCE_SET);
692 forward.private_deps().push_back(LabelTargetPair(&dest));
693 ASSERT_TRUE(forward.OnResolved(&err));
694 }
695
696 // Tests that configs are ordered properly between local and pulled ones.
TEST_F(TargetTest,ConfigOrdering)697 TEST_F(TargetTest, ConfigOrdering) {
698 TestWithScope setup;
699 Err err;
700
701 // Make Dep1. It has all_dependent_configs and public_configs.
702 TestTarget dep1(setup, "//:dep1", Target::SOURCE_SET);
703 Label dep1_all_config_label(SourceDir("//"), "dep1_all_config");
704 Config dep1_all_config(setup.settings(), dep1_all_config_label);
705 dep1_all_config.visibility().SetPublic();
706 ASSERT_TRUE(dep1_all_config.OnResolved(&err));
707 dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all_config));
708
709 Label dep1_public_config_label(SourceDir("//"), "dep1_public_config");
710 Config dep1_public_config(setup.settings(), dep1_public_config_label);
711 dep1_public_config.visibility().SetPublic();
712 ASSERT_TRUE(dep1_public_config.OnResolved(&err));
713 dep1.public_configs().push_back(LabelConfigPair(&dep1_public_config));
714 ASSERT_TRUE(dep1.OnResolved(&err));
715
716 // Make Dep2 with the same structure.
717 TestTarget dep2(setup, "//:dep2", Target::SOURCE_SET);
718 Label dep2_all_config_label(SourceDir("//"), "dep2_all_config");
719 Config dep2_all_config(setup.settings(), dep2_all_config_label);
720 dep2_all_config.visibility().SetPublic();
721 ASSERT_TRUE(dep2_all_config.OnResolved(&err));
722 dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all_config));
723
724 Label dep2_public_config_label(SourceDir("//"), "dep2_public_config");
725 Config dep2_public_config(setup.settings(), dep2_public_config_label);
726 dep2_public_config.visibility().SetPublic();
727 ASSERT_TRUE(dep2_public_config.OnResolved(&err));
728 dep2.public_configs().push_back(LabelConfigPair(&dep2_public_config));
729 ASSERT_TRUE(dep2.OnResolved(&err));
730
731 // This target depends on both previous targets.
732 TestTarget target(setup, "//:foo", Target::SOURCE_SET);
733 target.private_deps().push_back(LabelTargetPair(&dep1));
734 target.private_deps().push_back(LabelTargetPair(&dep2));
735
736 // It also has a private and public config.
737 Label public_config_label(SourceDir("//"), "public");
738 Config public_config(setup.settings(), public_config_label);
739 public_config.visibility().SetPublic();
740 ASSERT_TRUE(public_config.OnResolved(&err));
741 target.public_configs().push_back(LabelConfigPair(&public_config));
742
743 Label private_config_label(SourceDir("//"), "private");
744 Config private_config(setup.settings(), private_config_label);
745 private_config.visibility().SetPublic();
746 ASSERT_TRUE(private_config.OnResolved(&err));
747 target.configs().push_back(LabelConfigPair(&private_config));
748
749 // Resolve to get the computed list of configs applying.
750 ASSERT_TRUE(target.OnResolved(&err));
751 const auto& computed = target.configs();
752
753 // Order should be:
754 // 1. local private
755 // 2. local public
756 // 3. inherited all dependent
757 // 4. inherited public
758 ASSERT_EQ(6u, computed.size());
759 EXPECT_EQ(private_config_label, computed[0].label);
760 EXPECT_EQ(public_config_label, computed[1].label);
761 EXPECT_EQ(dep1_all_config_label, computed[2].label);
762 EXPECT_EQ(dep2_all_config_label, computed[3].label);
763 EXPECT_EQ(dep1_public_config_label, computed[4].label);
764 EXPECT_EQ(dep2_public_config_label, computed[5].label);
765 }
766
767 // Tests that different link/depend outputs work for solink tools.
TEST_F(TargetTest,LinkAndDepOutputs)768 TEST_F(TargetTest, LinkAndDepOutputs) {
769 TestWithScope setup;
770 Err err;
771
772 Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
773
774 std::unique_ptr<Tool> solink = Tool::CreateTool(CTool::kCToolSolink);
775 CTool* solink_tool = solink->AsC();
776 solink_tool->set_output_prefix("lib");
777 solink_tool->set_default_output_extension(".so");
778
779 const char kLinkPattern[] =
780 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}";
781 SubstitutionPattern link_output =
782 SubstitutionPattern::MakeForTest(kLinkPattern);
783 solink_tool->set_link_output(link_output);
784
785 const char kDependPattern[] =
786 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC";
787 SubstitutionPattern depend_output =
788 SubstitutionPattern::MakeForTest(kDependPattern);
789 solink_tool->set_depend_output(depend_output);
790
791 solink_tool->set_outputs(
792 SubstitutionList::MakeForTest(kLinkPattern, kDependPattern));
793
794 toolchain.SetTool(std::move(solink));
795
796 Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
797 target.set_output_type(Target::SHARED_LIBRARY);
798 target.SetToolchain(&toolchain);
799 ASSERT_TRUE(target.OnResolved(&err));
800
801 EXPECT_EQ("./liba.so", target.link_output_file().value());
802 EXPECT_EQ("./liba.so.TOC", target.dependency_output_file().value());
803
804 ASSERT_EQ(1u, target.runtime_outputs().size());
805 EXPECT_EQ("./liba.so", target.runtime_outputs()[0].value());
806 }
807
808 // Tests that runtime_outputs works without an explicit link_output for
809 // solink tools.
810 //
811 // Also tests GetOutputsAsSourceFiles() for binaries (the setup is the same).
TEST_F(TargetTest,RuntimeOuputs)812 TEST_F(TargetTest, RuntimeOuputs) {
813 TestWithScope setup;
814 Err err;
815
816 Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
817
818 std::unique_ptr<Tool> solink = Tool::CreateTool(CTool::kCToolSolink);
819 CTool* solink_tool = solink->AsC();
820 solink_tool->set_output_prefix("");
821 solink_tool->set_default_output_extension(".dll");
822
823 // Say the linker makes a DLL< an import library, and a symbol file we want
824 // to treat as a runtime output.
825 const char kLibPattern[] =
826 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib";
827 const char kDllPattern[] =
828 "{{root_out_dir}}/{{target_output_name}}{{output_extension}}";
829 const char kPdbPattern[] = "{{root_out_dir}}/{{target_output_name}}.pdb";
830 SubstitutionPattern pdb_pattern =
831 SubstitutionPattern::MakeForTest(kPdbPattern);
832
833 solink_tool->set_outputs(
834 SubstitutionList::MakeForTest(kLibPattern, kDllPattern, kPdbPattern));
835
836 // Say we only want the DLL and symbol file treaded as runtime outputs.
837 solink_tool->set_runtime_outputs(
838 SubstitutionList::MakeForTest(kDllPattern, kPdbPattern));
839
840 toolchain.SetTool(std::move(solink));
841
842 Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
843 target.set_output_type(Target::SHARED_LIBRARY);
844 target.SetToolchain(&toolchain);
845 ASSERT_TRUE(target.OnResolved(&err));
846
847 EXPECT_EQ("./a.dll.lib", target.link_output_file().value());
848 EXPECT_EQ("./a.dll.lib", target.dependency_output_file().value());
849
850 ASSERT_EQ(2u, target.runtime_outputs().size());
851 EXPECT_EQ("./a.dll", target.runtime_outputs()[0].value());
852 EXPECT_EQ("./a.pdb", target.runtime_outputs()[1].value());
853
854 // Test GetOutputsAsSourceFiles().
855 std::vector<SourceFile> computed_outputs;
856 EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
857 &computed_outputs, &err));
858 ASSERT_EQ(3u, computed_outputs.size());
859 EXPECT_EQ("//out/Debug/a.dll.lib", computed_outputs[0].value());
860 EXPECT_EQ("//out/Debug/a.dll", computed_outputs[1].value());
861 EXPECT_EQ("//out/Debug/a.pdb", computed_outputs[2].value());
862 }
863
864 // Tests Target::GetOutputFilesForSource for binary targets (these require a
865 // tool definition). Also tests GetOutputsAsSourceFiles() for source sets.
TEST_F(TargetTest,GetOutputFilesForSource_Binary)866 TEST_F(TargetTest, GetOutputFilesForSource_Binary) {
867 TestWithScope setup;
868
869 Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
870
871 std::unique_ptr<Tool> tool = Tool::CreateTool(CTool::kCToolCxx);
872 CTool* cxx = tool->AsC();
873 cxx->set_outputs(SubstitutionList::MakeForTest("{{source_file_part}}.o"));
874 toolchain.SetTool(std::move(tool));
875
876 Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
877 target.set_output_type(Target::SOURCE_SET);
878 target.SetToolchain(&toolchain);
879 Err err;
880 ASSERT_TRUE(target.OnResolved(&err));
881
882 const char* computed_tool_type = nullptr;
883 std::vector<OutputFile> output;
884 bool result = target.GetOutputFilesForSource(SourceFile("//source/input.cc"),
885 &computed_tool_type, &output);
886 ASSERT_TRUE(result);
887 EXPECT_EQ(std::string("cxx"), std::string(computed_tool_type));
888
889 // Outputs are relative to the build directory "//out/Debug/".
890 ASSERT_EQ(1u, output.size());
891 EXPECT_EQ("input.cc.o", output[0].value()) << output[0].value();
892
893 // Test GetOutputsAsSourceFiles(). Since this is a source set it should give a
894 // stamp file.
895 std::vector<SourceFile> computed_outputs;
896 EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
897 &computed_outputs, &err));
898 ASSERT_EQ(1u, computed_outputs.size());
899 EXPECT_EQ("//out/Debug/obj/a/a.stamp", computed_outputs[0].value());
900 }
901
TEST_F(TargetTest,CheckStampFileName)902 TEST_F(TargetTest, CheckStampFileName) {
903 TestWithScope setup;
904
905 Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
906
907 std::unique_ptr<Tool> tool = Tool::CreateTool(CTool::kCToolCxx);
908 CTool* cxx = tool->AsC();
909 cxx->set_outputs(SubstitutionList::MakeForTest("{{source_file_part}}.o"));
910 toolchain.SetTool(std::move(tool));
911
912 Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
913 target.set_output_type(Target::SOURCE_SET);
914 target.SetToolchain(&toolchain);
915
916 // Change the output artifact name on purpose.
917 target.set_output_name("b");
918
919 Err err;
920 ASSERT_TRUE(target.OnResolved(&err));
921
922 // Test GetOutputsAsSourceFiles(). Since this is a source set it should give a
923 // stamp file.
924 std::vector<SourceFile> computed_outputs;
925 EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
926 &computed_outputs, &err));
927 ASSERT_EQ(1u, computed_outputs.size());
928 EXPECT_EQ("//out/Debug/obj/a/a.stamp", computed_outputs[0].value())
929 << "was instead: " << computed_outputs[0].value();
930 }
931
932 // Tests Target::GetOutputFilesForSource for action_foreach targets (these, like
933 // copy targets, apply a pattern to the source file). Also tests
934 // GetOutputsAsSourceFiles() for action_foreach().
TEST_F(TargetTest,GetOutputFilesForSource_ActionForEach)935 TEST_F(TargetTest, GetOutputFilesForSource_ActionForEach) {
936 TestWithScope setup;
937
938 TestTarget target(setup, "//a:a", Target::ACTION_FOREACH);
939 target.sources().push_back(SourceFile("//a/source_file1.txt"));
940 target.sources().push_back(SourceFile("//a/source_file2.txt"));
941 target.action_values().outputs() =
942 SubstitutionList::MakeForTest("//out/Debug/{{source_file_part}}.one",
943 "//out/Debug/{{source_file_part}}.two");
944 Err err;
945 ASSERT_TRUE(target.OnResolved(&err));
946
947 const char* computed_tool_type = nullptr;
948 std::vector<OutputFile> output;
949 bool result = target.GetOutputFilesForSource(SourceFile("//source/input.txt"),
950 &computed_tool_type, &output);
951 ASSERT_TRUE(result);
952
953 // Outputs are relative to the build directory "//out/Debug/".
954 ASSERT_EQ(2u, output.size());
955 EXPECT_EQ("input.txt.one", output[0].value());
956 EXPECT_EQ("input.txt.two", output[1].value());
957
958 // Test GetOutputsAsSourceFiles(). It should give both outputs for each of the
959 // two inputs.
960 std::vector<SourceFile> computed_outputs;
961 EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
962 &computed_outputs, &err));
963 ASSERT_EQ(4u, computed_outputs.size());
964 EXPECT_EQ("//out/Debug/source_file1.txt.one", computed_outputs[0].value());
965 EXPECT_EQ("//out/Debug/source_file1.txt.two", computed_outputs[1].value());
966 EXPECT_EQ("//out/Debug/source_file2.txt.one", computed_outputs[2].value());
967 EXPECT_EQ("//out/Debug/source_file2.txt.two", computed_outputs[3].value());
968 }
969
970 // Tests Target::GetOutputFilesForSource for action targets (these just list the
971 // output of the action as the result of all possible inputs). This should also
972 // cover everything other than binary, action_foreach, and copy targets.
TEST_F(TargetTest,GetOutputFilesForSource_Action)973 TEST_F(TargetTest, GetOutputFilesForSource_Action) {
974 TestWithScope setup;
975
976 TestTarget target(setup, "//a:a", Target::ACTION);
977 target.sources().push_back(SourceFile("//a/source_file1.txt"));
978 target.action_values().outputs() =
979 SubstitutionList::MakeForTest("//out/Debug/one", "//out/Debug/two");
980 Err err;
981 ASSERT_TRUE(target.OnResolved(&err));
982
983 const char* computed_tool_type = nullptr;
984 std::vector<OutputFile> output;
985 bool result = target.GetOutputFilesForSource(SourceFile("//source/input.txt"),
986 &computed_tool_type, &output);
987 ASSERT_TRUE(result);
988
989 // Outputs are relative to the build directory "//out/Debug/".
990 ASSERT_EQ(2u, output.size());
991 EXPECT_EQ("one", output[0].value());
992 EXPECT_EQ("two", output[1].value());
993
994 // Test GetOutputsAsSourceFiles(). It should give the listed outputs.
995 std::vector<SourceFile> computed_outputs;
996 EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
997 &computed_outputs, &err));
998 ASSERT_EQ(2u, computed_outputs.size());
999 EXPECT_EQ("//out/Debug/one", computed_outputs[0].value());
1000 EXPECT_EQ("//out/Debug/two", computed_outputs[1].value());
1001
1002 // Test that the copy target type behaves the same. This target requires only
1003 // one output.
1004 target.action_values().outputs() =
1005 SubstitutionList::MakeForTest("//out/Debug/one");
1006 target.set_output_type(Target::COPY_FILES);
1007
1008 // Outputs are relative to the build directory "//out/Debug/".
1009 result = target.GetOutputFilesForSource(SourceFile("//source/input.txt"),
1010 &computed_tool_type, &output);
1011 ASSERT_TRUE(result);
1012 ASSERT_EQ(1u, output.size());
1013 EXPECT_EQ("one", output[0].value());
1014
1015 // Test GetOutputsAsSourceFiles() for the copy case.
1016 EXPECT_TRUE(target.GetOutputsAsSourceFiles(LocationRange(), true,
1017 &computed_outputs, &err));
1018 ASSERT_EQ(1u, computed_outputs.size()) << computed_outputs.size();
1019 EXPECT_EQ("//out/Debug/one", computed_outputs[0].value());
1020 }
1021
1022 // Shared libraries should be inherited across public shared library
1023 // boundaries.
TEST_F(TargetTest,SharedInheritance)1024 TEST_F(TargetTest, SharedInheritance) {
1025 TestWithScope setup;
1026 Err err;
1027
1028 // Create two leaf shared libraries.
1029 TestTarget pub(setup, "//foo:pub", Target::SHARED_LIBRARY);
1030 ASSERT_TRUE(pub.OnResolved(&err));
1031
1032 TestTarget priv(setup, "//foo:priv", Target::SHARED_LIBRARY);
1033 ASSERT_TRUE(priv.OnResolved(&err));
1034
1035 // Intermediate shared library with the leaf shared libraries as
1036 // dependencies, one public, one private.
1037 TestTarget inter(setup, "//foo:inter", Target::SHARED_LIBRARY);
1038 inter.public_deps().push_back(LabelTargetPair(&pub));
1039 inter.private_deps().push_back(LabelTargetPair(&priv));
1040 ASSERT_TRUE(inter.OnResolved(&err));
1041
1042 // The intermediate shared library should have both "pub" and "priv" in its
1043 // inherited libraries.
1044 std::vector<const Target*> inter_inherited =
1045 inter.inherited_libraries().GetOrdered();
1046 ASSERT_EQ(2u, inter_inherited.size());
1047 EXPECT_EQ(&pub, inter_inherited[0]);
1048 EXPECT_EQ(&priv, inter_inherited[1]);
1049
1050 // Make a toplevel executable target depending on the intermediate one.
1051 TestTarget exe(setup, "//foo:exe", Target::SHARED_LIBRARY);
1052 exe.private_deps().push_back(LabelTargetPair(&inter));
1053 ASSERT_TRUE(exe.OnResolved(&err));
1054
1055 // The exe's inherited libraries should be "inter" (because it depended
1056 // directly on it) and "pub" (because inter depended publicly on it).
1057 std::vector<const Target*> exe_inherited =
1058 exe.inherited_libraries().GetOrdered();
1059 ASSERT_EQ(2u, exe_inherited.size());
1060 EXPECT_EQ(&inter, exe_inherited[0]);
1061 EXPECT_EQ(&pub, exe_inherited[1]);
1062 }
1063
TEST_F(TargetTest,GeneratedInputs)1064 TEST_F(TargetTest, GeneratedInputs) {
1065 TestWithScope setup;
1066 Err err;
1067
1068 SourceFile generated_file("//out/Debug/generated.cc");
1069
1070 // This target has a generated input and no dependency makes it.
1071 TestTarget non_existent_generator(setup, "//foo:non_existent_generator",
1072 Target::EXECUTABLE);
1073 non_existent_generator.sources().push_back(generated_file);
1074 EXPECT_TRUE(non_existent_generator.OnResolved(&err)) << err.message();
1075 AssertSchedulerHasOneUnknownFileMatching(&non_existent_generator,
1076 generated_file);
1077 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1078
1079 // Make a target that generates the file.
1080 TestTarget generator(setup, "//foo:generator", Target::ACTION);
1081 generator.action_values().outputs() =
1082 SubstitutionList::MakeForTest(generated_file.value().c_str());
1083 err = Err();
1084 EXPECT_TRUE(generator.OnResolved(&err)) << err.message();
1085
1086 // A target that depends on the generator that uses the file as a source
1087 // should be OK. This uses a private dep (will be used later).
1088 TestTarget existent_generator(setup, "//foo:existent_generator",
1089 Target::SHARED_LIBRARY);
1090 existent_generator.sources().push_back(generated_file);
1091 existent_generator.private_deps().push_back(LabelTargetPair(&generator));
1092 EXPECT_TRUE(existent_generator.OnResolved(&err)) << err.message();
1093 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1094
1095 // A target that depends on the previous one should *not* be allowed to
1096 // use the generated file, because existent_generator used private deps.
1097 // This is:
1098 // indirect_private --> existent_generator --[private]--> generator
1099 TestTarget indirect_private(setup, "//foo:indirect_private",
1100 Target::EXECUTABLE);
1101 indirect_private.sources().push_back(generated_file);
1102 indirect_private.public_deps().push_back(
1103 LabelTargetPair(&existent_generator));
1104 EXPECT_TRUE(indirect_private.OnResolved(&err));
1105 AssertSchedulerHasOneUnknownFileMatching(&indirect_private, generated_file);
1106 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1107
1108 // Now make a chain like the above but with all public deps, it should be OK.
1109 TestTarget existent_public(setup, "//foo:existent_public",
1110 Target::SHARED_LIBRARY);
1111 existent_public.public_deps().push_back(LabelTargetPair(&generator));
1112 EXPECT_TRUE(existent_public.OnResolved(&err)) << err.message();
1113 TestTarget indirect_public(setup, "//foo:indirect_public",
1114 Target::EXECUTABLE);
1115 indirect_public.sources().push_back(generated_file);
1116 indirect_public.public_deps().push_back(LabelTargetPair(&existent_public));
1117 EXPECT_TRUE(indirect_public.OnResolved(&err)) << err.message();
1118 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1119 }
1120
1121 // This is sort of a Scheduler test, but is related to the above test more.
TEST_F(TargetTest,WriteFileGeneratedInputs)1122 TEST_F(TargetTest, WriteFileGeneratedInputs) {
1123 TestWithScope setup;
1124 Err err;
1125
1126 SourceFile generated_file("//out/Debug/generated.data");
1127
1128 // This target has a generated input and no dependency makes it.
1129 TestTarget non_existent_generator(setup, "//foo:non_existent_generator",
1130 Target::EXECUTABLE);
1131 non_existent_generator.sources().push_back(generated_file);
1132 EXPECT_TRUE(non_existent_generator.OnResolved(&err));
1133 AssertSchedulerHasOneUnknownFileMatching(&non_existent_generator,
1134 generated_file);
1135 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1136
1137 // This target has a generated file and we've decared we write it.
1138 TestTarget existent_generator(setup, "//foo:existent_generator",
1139 Target::EXECUTABLE);
1140 existent_generator.sources().push_back(generated_file);
1141 EXPECT_TRUE(existent_generator.OnResolved(&err));
1142 scheduler().AddWrittenFile(generated_file);
1143
1144 // Should be OK.
1145 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1146 }
1147
TEST_F(TargetTest,WriteRuntimeDepsGeneratedInputs)1148 TEST_F(TargetTest, WriteRuntimeDepsGeneratedInputs) {
1149 TestWithScope setup;
1150 Err err;
1151
1152 SourceFile source_file("//out/Debug/generated.runtime_deps");
1153 OutputFile output_file(setup.build_settings(), source_file);
1154
1155 TestTarget generator(setup, "//foo:generator", Target::EXECUTABLE);
1156 generator.set_write_runtime_deps_output(output_file);
1157 g_scheduler->AddWriteRuntimeDepsTarget(&generator);
1158
1159 TestTarget middle_data_dep(setup, "//foo:middle", Target::EXECUTABLE);
1160 middle_data_dep.data_deps().push_back(LabelTargetPair(&generator));
1161
1162 // This target has a generated input and no dependency makes it.
1163 TestTarget dep_missing(setup, "//foo:no_dep", Target::EXECUTABLE);
1164 dep_missing.sources().push_back(source_file);
1165 EXPECT_TRUE(dep_missing.OnResolved(&err));
1166 AssertSchedulerHasOneUnknownFileMatching(&dep_missing, source_file);
1167 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1168
1169 // This target has a generated file and we've directly dependended on it.
1170 TestTarget dep_present(setup, "//foo:with_dep", Target::EXECUTABLE);
1171 dep_present.sources().push_back(source_file);
1172 dep_present.private_deps().push_back(LabelTargetPair(&generator));
1173 EXPECT_TRUE(dep_present.OnResolved(&err));
1174 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1175
1176 // This target has a generated file and we've indirectly dependended on it
1177 // via data_deps.
1178 TestTarget dep_indirect(setup, "//foo:with_dep", Target::EXECUTABLE);
1179 dep_indirect.sources().push_back(source_file);
1180 dep_indirect.data_deps().push_back(LabelTargetPair(&middle_data_dep));
1181 EXPECT_TRUE(dep_indirect.OnResolved(&err));
1182 AssertSchedulerHasOneUnknownFileMatching(&dep_indirect, source_file);
1183 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1184
1185 // This target has a generated file and we've directly dependended on it
1186 // via data_deps.
1187 TestTarget data_dep_present(setup, "//foo:with_dep", Target::EXECUTABLE);
1188 data_dep_present.sources().push_back(source_file);
1189 data_dep_present.data_deps().push_back(LabelTargetPair(&generator));
1190 EXPECT_TRUE(data_dep_present.OnResolved(&err));
1191 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1192 }
1193
1194 // Tests that intermediate object files generated by binary targets are also
1195 // considered generated for the purposes of input checking. Above, we tested
1196 // the failure cases for generated inputs, so here only test .o files that are
1197 // present.
TEST_F(TargetTest,ObjectGeneratedInputs)1198 TEST_F(TargetTest, ObjectGeneratedInputs) {
1199 TestWithScope setup;
1200 Err err;
1201
1202 // This target compiles the source.
1203 SourceFile source_file("//source.cc");
1204 TestTarget source_generator(setup, "//:source_target", Target::SOURCE_SET);
1205 source_generator.sources().push_back(source_file);
1206 EXPECT_TRUE(source_generator.OnResolved(&err));
1207
1208 // This is the object file that the test toolchain generates for the source.
1209 SourceFile object_file("//out/Debug/obj/source_target.source.o");
1210
1211 TestTarget final_target(setup, "//:final", Target::ACTION);
1212 final_target.config_values().inputs().push_back(object_file);
1213 EXPECT_TRUE(final_target.OnResolved(&err));
1214
1215 AssertSchedulerHasOneUnknownFileMatching(&final_target, object_file);
1216 }
1217
TEST_F(TargetTest,ResolvePrecompiledHeaders)1218 TEST_F(TargetTest, ResolvePrecompiledHeaders) {
1219 TestWithScope setup;
1220 Err err;
1221
1222 Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
1223
1224 // Target with no settings, no configs, should be a no-op.
1225 EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
1226
1227 // Config with PCH values.
1228 Config config_1(setup.settings(), Label(SourceDir("//foo/"), "c1"));
1229 std::string pch_1("pch.h");
1230 SourceFile pcs_1("//pcs.cc");
1231 config_1.own_values().set_precompiled_header(pch_1);
1232 config_1.own_values().set_precompiled_source(pcs_1);
1233 ASSERT_TRUE(config_1.OnResolved(&err));
1234 target.configs().push_back(LabelConfigPair(&config_1));
1235
1236 // No PCH info specified on TargetTest, but the config specifies one, the
1237 // values should get copied to the target.
1238 EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
1239 EXPECT_EQ(pch_1, target.config_values().precompiled_header());
1240 EXPECT_TRUE(target.config_values().precompiled_source() == pcs_1);
1241
1242 // Now both target and config have matching PCH values. Resolving again
1243 // should be a no-op since they all match.
1244 EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
1245 EXPECT_TRUE(target.config_values().precompiled_header() == pch_1);
1246 EXPECT_TRUE(target.config_values().precompiled_source() == pcs_1);
1247
1248 // Second config with different PCH values.
1249 Config config_2(setup.settings(), Label(SourceDir("//foo/"), "c2"));
1250 std::string pch_2("pch2.h");
1251 SourceFile pcs_2("//pcs2.cc");
1252 config_2.own_values().set_precompiled_header(pch_2);
1253 config_2.own_values().set_precompiled_source(pcs_2);
1254 ASSERT_TRUE(config_2.OnResolved(&err));
1255 target.configs().push_back(LabelConfigPair(&config_2));
1256
1257 // This should be an error since they don't match.
1258 EXPECT_FALSE(target.ResolvePrecompiledHeaders(&err));
1259
1260 // Make sure the proper labels are blamed.
1261 EXPECT_EQ(
1262 "The target //foo:bar\n"
1263 "has conflicting precompiled header settings.\n"
1264 "\n"
1265 "From //foo:bar\n"
1266 " header: pch.h\n"
1267 " source: //pcs.cc\n"
1268 "\n"
1269 "From //foo:c2\n"
1270 " header: pch2.h\n"
1271 " source: //pcs2.cc",
1272 err.help_text());
1273 }
1274
TEST_F(TargetTest,AssertNoDeps)1275 TEST_F(TargetTest, AssertNoDeps) {
1276 TestWithScope setup;
1277 Err err;
1278
1279 // A target.
1280 TestTarget a(setup, "//a", Target::SHARED_LIBRARY);
1281 ASSERT_TRUE(a.OnResolved(&err));
1282
1283 // B depends on A and has an assert_no_deps for a random dir.
1284 TestTarget b(setup, "//b", Target::SHARED_LIBRARY);
1285 b.private_deps().push_back(LabelTargetPair(&a));
1286 b.assert_no_deps().push_back(LabelPattern(LabelPattern::RECURSIVE_DIRECTORY,
1287 SourceDir("//disallowed/"),
1288 std::string(), Label()));
1289 ASSERT_TRUE(b.OnResolved(&err));
1290
1291 LabelPattern disallow_a(LabelPattern::RECURSIVE_DIRECTORY, SourceDir("//a/"),
1292 std::string(), Label());
1293
1294 // C depends on B and disallows depending on A. This should fail.
1295 TestTarget c(setup, "//c", Target::EXECUTABLE);
1296 c.private_deps().push_back(LabelTargetPair(&b));
1297 c.assert_no_deps().push_back(disallow_a);
1298 ASSERT_FALSE(c.OnResolved(&err));
1299
1300 // Validate the error message has the proper path.
1301 EXPECT_EQ(
1302 "//c:c has an assert_no_deps entry:\n"
1303 " //a/*\n"
1304 "which fails for the dependency path:\n"
1305 " //c:c ->\n"
1306 " //b:b ->\n"
1307 " //a:a",
1308 err.help_text());
1309 err = Err();
1310
1311 // Add an intermediate executable with: exe -> b -> a
1312 TestTarget exe(setup, "//exe", Target::EXECUTABLE);
1313 exe.private_deps().push_back(LabelTargetPair(&b));
1314 ASSERT_TRUE(exe.OnResolved(&err));
1315
1316 // D depends on the executable and disallows depending on A. Since there is
1317 // an intermediate executable, this should be OK.
1318 TestTarget d(setup, "//d", Target::EXECUTABLE);
1319 d.private_deps().push_back(LabelTargetPair(&exe));
1320 d.assert_no_deps().push_back(disallow_a);
1321 ASSERT_TRUE(d.OnResolved(&err));
1322
1323 // A2 disallows depending on anything in its own directory, but the
1324 // assertions should not match the target itself so this should be OK.
1325 TestTarget a2(setup, "//a:a2", Target::EXECUTABLE);
1326 a2.assert_no_deps().push_back(disallow_a);
1327 ASSERT_TRUE(a2.OnResolved(&err));
1328 }
1329
TEST_F(TargetTest,PullRecursiveBundleData)1330 TEST_F(TargetTest, PullRecursiveBundleData) {
1331 TestWithScope setup;
1332 Err err;
1333
1334 // We have the following dependency graph:
1335 // A (create_bundle) -> B (bundle_data)
1336 // \-> C (create_bundle) -> D (bundle_data)
1337 // \-> E (group) -> F (bundle_data)
1338 // \-> B (bundle_data)
1339 TestTarget a(setup, "//foo:a", Target::CREATE_BUNDLE);
1340 TestTarget b(setup, "//foo:b", Target::BUNDLE_DATA);
1341 TestTarget c(setup, "//foo:c", Target::CREATE_BUNDLE);
1342 TestTarget d(setup, "//foo:d", Target::BUNDLE_DATA);
1343 TestTarget e(setup, "//foo:e", Target::GROUP);
1344 TestTarget f(setup, "//foo:f", Target::BUNDLE_DATA);
1345 a.public_deps().push_back(LabelTargetPair(&b));
1346 a.public_deps().push_back(LabelTargetPair(&c));
1347 a.public_deps().push_back(LabelTargetPair(&e));
1348 c.public_deps().push_back(LabelTargetPair(&d));
1349 e.public_deps().push_back(LabelTargetPair(&f));
1350 e.public_deps().push_back(LabelTargetPair(&b));
1351
1352 a.bundle_data().root_dir() = SourceDir("//out/foo_a.bundle");
1353 a.bundle_data().resources_dir() = SourceDir("//out/foo_a.bundle/Resources");
1354
1355 b.sources().push_back(SourceFile("//foo/b1.txt"));
1356 b.sources().push_back(SourceFile("//foo/b2.txt"));
1357 b.action_values().outputs() = SubstitutionList::MakeForTest(
1358 "{{bundle_resources_dir}}/{{source_file_part}}");
1359 ASSERT_TRUE(b.OnResolved(&err));
1360
1361 c.bundle_data().root_dir() = SourceDir("//out/foo_c.bundle");
1362 c.bundle_data().resources_dir() = SourceDir("//out/foo_c.bundle/Resources");
1363
1364 d.sources().push_back(SourceFile("//foo/d.txt"));
1365 d.action_values().outputs() = SubstitutionList::MakeForTest(
1366 "{{bundle_resources_dir}}/{{source_file_part}}");
1367 ASSERT_TRUE(d.OnResolved(&err));
1368
1369 f.sources().push_back(SourceFile("//foo/f1.txt"));
1370 f.sources().push_back(SourceFile("//foo/f2.txt"));
1371 f.sources().push_back(SourceFile("//foo/f3.txt"));
1372 f.sources().push_back(
1373 SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
1374 f.sources().push_back(
1375 SourceFile("//foo/Foo.xcassets/foo.imageset/FooEmpty-29.png"));
1376 f.sources().push_back(
1377 SourceFile("//foo/Foo.xcassets/foo.imageset/FooEmpty-29@2x.png"));
1378 f.sources().push_back(
1379 SourceFile("//foo/Foo.xcassets/foo.imageset/FooEmpty-29@3x.png"));
1380 f.action_values().outputs() = SubstitutionList::MakeForTest(
1381 "{{bundle_resources_dir}}/{{source_file_part}}");
1382 ASSERT_TRUE(f.OnResolved(&err));
1383
1384 ASSERT_TRUE(e.OnResolved(&err));
1385 ASSERT_TRUE(c.OnResolved(&err));
1386 ASSERT_TRUE(a.OnResolved(&err));
1387
1388 // A gets its data from B and F.
1389 ASSERT_EQ(a.bundle_data().file_rules().size(), 2u);
1390 ASSERT_EQ(a.bundle_data().file_rules()[0].sources().size(), 2u);
1391 ASSERT_EQ(a.bundle_data().file_rules()[1].sources().size(), 3u);
1392 ASSERT_EQ(a.bundle_data().assets_catalog_sources().size(), 1u);
1393 ASSERT_EQ(a.bundle_data().bundle_deps().size(), 2u);
1394
1395 // C gets its data from D.
1396 ASSERT_EQ(c.bundle_data().file_rules().size(), 1u);
1397 ASSERT_EQ(c.bundle_data().file_rules()[0].sources().size(), 1u);
1398 ASSERT_EQ(c.bundle_data().bundle_deps().size(), 1u);
1399
1400 // E does not have any bundle_data information but gets a list of
1401 // bundle_deps to propagate them during target resolution.
1402 ASSERT_TRUE(e.bundle_data().file_rules().empty());
1403 ASSERT_TRUE(e.bundle_data().assets_catalog_sources().empty());
1404 ASSERT_EQ(e.bundle_data().bundle_deps().size(), 2u);
1405 }
1406
TEST(TargetTest,CollectMetadataNoRecurse)1407 TEST(TargetTest, CollectMetadataNoRecurse) {
1408 TestWithScope setup;
1409
1410 TestTarget one(setup, "//foo:one", Target::SOURCE_SET);
1411 Value a_expected(nullptr, Value::LIST);
1412 a_expected.list_value().push_back(Value(nullptr, "foo"));
1413 one.metadata().contents().insert(
1414 std::pair<std::string_view, Value>("a", a_expected));
1415
1416 Value b_expected(nullptr, Value::LIST);
1417 b_expected.list_value().push_back(Value(nullptr, true));
1418 one.metadata().contents().insert(
1419 std::pair<std::string_view, Value>("b", b_expected));
1420
1421 one.metadata().set_source_dir(SourceDir("/usr/home/files/"));
1422
1423 std::vector<std::string> data_keys;
1424 data_keys.push_back("a");
1425 data_keys.push_back("b");
1426
1427 std::vector<std::string> walk_keys;
1428
1429 Err err;
1430 std::vector<Value> result;
1431 TargetSet targets;
1432 one.GetMetadata(data_keys, walk_keys, SourceDir(), false, &result, &targets,
1433 &err);
1434 EXPECT_FALSE(err.has_error());
1435
1436 std::vector<Value> expected;
1437 expected.push_back(Value(nullptr, "foo"));
1438 expected.push_back(Value(nullptr, true));
1439 EXPECT_EQ(result, expected);
1440 }
1441
TEST(TargetTest,CollectMetadataWithRecurse)1442 TEST(TargetTest, CollectMetadataWithRecurse) {
1443 TestWithScope setup;
1444
1445 TestTarget one(setup, "//foo:one", Target::SOURCE_SET);
1446 Value a_expected(nullptr, Value::LIST);
1447 a_expected.list_value().push_back(Value(nullptr, "foo"));
1448 one.metadata().contents().insert(
1449 std::pair<std::string_view, Value>("a", a_expected));
1450
1451 Value b_expected(nullptr, Value::LIST);
1452 b_expected.list_value().push_back(Value(nullptr, true));
1453 one.metadata().contents().insert(
1454 std::pair<std::string_view, Value>("b", b_expected));
1455
1456 TestTarget two(setup, "//foo:two", Target::SOURCE_SET);
1457 Value a_2_expected(nullptr, Value::LIST);
1458 a_2_expected.list_value().push_back(Value(nullptr, "bar"));
1459 two.metadata().contents().insert(
1460 std::pair<std::string_view, Value>("a", a_2_expected));
1461
1462 one.public_deps().push_back(LabelTargetPair(&two));
1463
1464 std::vector<std::string> data_keys;
1465 data_keys.push_back("a");
1466 data_keys.push_back("b");
1467
1468 std::vector<std::string> walk_keys;
1469
1470 Err err;
1471 std::vector<Value> result;
1472 TargetSet targets;
1473 one.GetMetadata(data_keys, walk_keys, SourceDir(), false, &result, &targets,
1474 &err);
1475 EXPECT_FALSE(err.has_error());
1476
1477 std::vector<Value> expected;
1478 expected.push_back(Value(nullptr, "bar"));
1479 expected.push_back(Value(nullptr, "foo"));
1480 expected.push_back(Value(nullptr, true));
1481 EXPECT_EQ(result, expected);
1482 }
1483
TEST(TargetTest,CollectMetadataWithRecurseHole)1484 TEST(TargetTest, CollectMetadataWithRecurseHole) {
1485 TestWithScope setup;
1486
1487 TestTarget one(setup, "//foo:one", Target::SOURCE_SET);
1488 Value a_expected(nullptr, Value::LIST);
1489 a_expected.list_value().push_back(Value(nullptr, "foo"));
1490 one.metadata().contents().insert(
1491 std::pair<std::string_view, Value>("a", a_expected));
1492
1493 Value b_expected(nullptr, Value::LIST);
1494 b_expected.list_value().push_back(Value(nullptr, true));
1495 one.metadata().contents().insert(
1496 std::pair<std::string_view, Value>("b", b_expected));
1497
1498 // Target two does not have metadata but depends on three
1499 // which does.
1500 TestTarget two(setup, "//foo:two", Target::SOURCE_SET);
1501
1502 TestTarget three(setup, "//foo:three", Target::SOURCE_SET);
1503 Value a_3_expected(nullptr, Value::LIST);
1504 a_3_expected.list_value().push_back(Value(nullptr, "bar"));
1505 three.metadata().contents().insert(
1506 std::pair<std::string_view, Value>("a", a_3_expected));
1507
1508 one.public_deps().push_back(LabelTargetPair(&two));
1509 two.public_deps().push_back(LabelTargetPair(&three));
1510
1511 std::vector<std::string> data_keys;
1512 data_keys.push_back("a");
1513 data_keys.push_back("b");
1514
1515 std::vector<std::string> walk_keys;
1516
1517 Err err;
1518 std::vector<Value> result;
1519 TargetSet targets;
1520 one.GetMetadata(data_keys, walk_keys, SourceDir(), false, &result, &targets,
1521 &err);
1522 EXPECT_FALSE(err.has_error());
1523
1524 std::vector<Value> expected;
1525 expected.push_back(Value(nullptr, "bar"));
1526 expected.push_back(Value(nullptr, "foo"));
1527 expected.push_back(Value(nullptr, true));
1528 EXPECT_EQ(result, expected);
1529 }
1530
TEST(TargetTest,CollectMetadataWithBarrier)1531 TEST(TargetTest, CollectMetadataWithBarrier) {
1532 TestWithScope setup;
1533
1534 TestTarget one(setup, "//foo:one", Target::SOURCE_SET);
1535 Value a_expected(nullptr, Value::LIST);
1536 a_expected.list_value().push_back(Value(nullptr, "foo"));
1537 one.metadata().contents().insert(
1538 std::pair<std::string_view, Value>("a", a_expected));
1539
1540 Value walk_expected(nullptr, Value::LIST);
1541 walk_expected.list_value().push_back(Value(nullptr, "two"));
1542 one.metadata().contents().insert(
1543 std::pair<std::string_view, Value>("walk", walk_expected));
1544
1545 TestTarget two(setup, "//foo/two:two", Target::SOURCE_SET);
1546 Value a_2_expected(nullptr, Value::LIST);
1547 a_2_expected.list_value().push_back(Value(nullptr, "bar"));
1548 two.metadata().contents().insert(
1549 std::pair<std::string_view, Value>("a", a_2_expected));
1550
1551 TestTarget three(setup, "//foo:three", Target::SOURCE_SET);
1552 Value a_3_expected(nullptr, Value::LIST);
1553 a_3_expected.list_value().push_back(Value(nullptr, "baz"));
1554 three.metadata().contents().insert(
1555 std::pair<std::string_view, Value>("a", a_3_expected));
1556
1557 one.private_deps().push_back(LabelTargetPair(&two));
1558 one.public_deps().push_back(LabelTargetPair(&three));
1559
1560 std::vector<std::string> data_keys;
1561 data_keys.push_back("a");
1562
1563 std::vector<std::string> walk_keys;
1564 walk_keys.push_back("walk");
1565
1566 Err err;
1567 std::vector<Value> result;
1568 TargetSet targets;
1569 one.GetMetadata(data_keys, walk_keys, SourceDir(), false, &result, &targets,
1570 &err);
1571 EXPECT_FALSE(err.has_error()) << err.message();
1572
1573 std::vector<Value> expected;
1574 expected.push_back(Value(nullptr, "bar"));
1575 expected.push_back(Value(nullptr, "foo"));
1576 EXPECT_EQ(result, expected) << result.size();
1577 }
1578
TEST(TargetTest,CollectMetadataWithError)1579 TEST(TargetTest, CollectMetadataWithError) {
1580 TestWithScope setup;
1581
1582 TestTarget one(setup, "//foo:one", Target::SOURCE_SET);
1583 Value a_expected(nullptr, Value::LIST);
1584 a_expected.list_value().push_back(Value(nullptr, "foo"));
1585 one.metadata().contents().insert(
1586 std::pair<std::string_view, Value>("a", a_expected));
1587
1588 Value walk_expected(nullptr, Value::LIST);
1589 walk_expected.list_value().push_back(Value(nullptr, "//foo:missing"));
1590 one.metadata().contents().insert(
1591 std::pair<std::string_view, Value>("walk", walk_expected));
1592
1593 std::vector<std::string> data_keys;
1594 data_keys.push_back("a");
1595
1596 std::vector<std::string> walk_keys;
1597 walk_keys.push_back("walk");
1598
1599 Err err;
1600 std::vector<Value> result;
1601 TargetSet targets;
1602 one.GetMetadata(data_keys, walk_keys, SourceDir(), false, &result, &targets,
1603 &err);
1604 EXPECT_TRUE(err.has_error());
1605 EXPECT_EQ(err.message(),
1606 "I was expecting //foo:missing(//toolchain:default) to be a "
1607 "dependency of //foo:one(//toolchain:default). "
1608 "Make sure it's included in the deps or data_deps, and that you've "
1609 "specified the appropriate toolchain.")
1610 << err.message();
1611 }
1612
TEST_F(TargetTest,WriteMetadataCollection)1613 TEST_F(TargetTest, WriteMetadataCollection) {
1614 TestWithScope setup;
1615 Err err;
1616
1617 SourceFile source_file("//out/Debug/metadata.json");
1618 OutputFile output_file(setup.build_settings(), source_file);
1619
1620 TestTarget generator(setup, "//foo:write", Target::GENERATED_FILE);
1621 generator.action_values().outputs() =
1622 SubstitutionList::MakeForTest("//out/Debug/metadata.json");
1623 EXPECT_TRUE(generator.OnResolved(&err));
1624
1625 TestTarget middle_data_dep(setup, "//foo:middle", Target::EXECUTABLE);
1626 middle_data_dep.data_deps().push_back(LabelTargetPair(&generator));
1627 EXPECT_TRUE(middle_data_dep.OnResolved(&err));
1628
1629 // This target has a generated metadata input and no dependency makes it.
1630 TestTarget dep_missing(setup, "//foo:no_dep", Target::EXECUTABLE);
1631 dep_missing.sources().push_back(source_file);
1632 EXPECT_TRUE(dep_missing.OnResolved(&err));
1633 AssertSchedulerHasOneUnknownFileMatching(&dep_missing, source_file);
1634 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1635
1636 // This target has a generated file and we've directly dependended on it.
1637 TestTarget dep_present(setup, "//foo:with_dep", Target::EXECUTABLE);
1638 dep_present.sources().push_back(source_file);
1639 dep_present.private_deps().push_back(LabelTargetPair(&generator));
1640 EXPECT_TRUE(dep_present.OnResolved(&err));
1641 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1642
1643 // This target has a generated file and we've indirectly dependended on it
1644 // via data_deps.
1645 TestTarget dep_indirect(setup, "//foo:indirect_dep", Target::EXECUTABLE);
1646 dep_indirect.sources().push_back(source_file);
1647 dep_indirect.data_deps().push_back(LabelTargetPair(&middle_data_dep));
1648 EXPECT_TRUE(dep_indirect.OnResolved(&err));
1649 AssertSchedulerHasOneUnknownFileMatching(&dep_indirect, source_file);
1650 scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
1651
1652 // This target has a generated file and we've directly dependended on it
1653 // via data_deps.
1654 TestTarget data_dep_present(setup, "//foo:with_data_dep", Target::EXECUTABLE);
1655 data_dep_present.sources().push_back(source_file);
1656 data_dep_present.data_deps().push_back(LabelTargetPair(&generator));
1657 EXPECT_TRUE(data_dep_present.OnResolved(&err));
1658 EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
1659 }
1660
1661 // Tests that modulemap files use the cxx_module tool.
TEST_F(TargetTest,ModuleMap)1662 TEST_F(TargetTest, ModuleMap) {
1663 TestWithScope setup;
1664
1665 Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
1666
1667 std::unique_ptr<Tool> tool = Tool::CreateTool(CTool::kCToolCxxModule);
1668 CTool* cxx_module = tool->AsC();
1669 cxx_module->set_outputs(
1670 SubstitutionList::MakeForTest("{{source_file_part}}.pcm"));
1671 toolchain.SetTool(std::move(tool));
1672
1673 Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
1674 target.set_output_type(Target::SOURCE_SET);
1675 target.SetToolchain(&toolchain);
1676 Err err;
1677 ASSERT_TRUE(target.OnResolved(&err));
1678
1679 const char* computed_tool_type = nullptr;
1680 std::vector<OutputFile> output;
1681 bool result = target.GetOutputFilesForSource(
1682 SourceFile("//source/input.modulemap"), &computed_tool_type, &output);
1683 ASSERT_TRUE(result);
1684 EXPECT_EQ(std::string("cxx_module"), std::string(computed_tool_type));
1685
1686 // Outputs are relative to the build directory "//out/Debug/".
1687 ASSERT_EQ(1u, output.size());
1688 EXPECT_EQ("input.modulemap.pcm", output[0].value()) << output[0].value();
1689 }
1690