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