29 "build out: cat in | implicit\n"));
31 fs_.Create(
"out",
"");
34 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
45 "build out: cat in | implicit\n"));
47 fs_.Create(
"out",
"");
49 fs_.Create(
"implicit",
"");
52 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
63 " command = cat $in > $out\n" 64 "build out.o: catdep foo.cc\n"));
65 fs_.Create(
"foo.cc",
"");
66 fs_.Create(
"out.o.d",
"out.o: ./foo/../implicit.h\n");
67 fs_.Create(
"out.o",
"");
69 fs_.Create(
"implicit.h",
"");
72 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
84 " command = cat $in > $out\n" 85 "build implicit.h: cat data\n" 86 "build out.o: catdep foo.cc || implicit.h\n"));
87 fs_.Create(
"implicit.h",
"");
88 fs_.Create(
"foo.cc",
"");
89 fs_.Create(
"out.o.d",
"out.o: implicit.h\n");
90 fs_.Create(
"out.o",
"");
92 fs_.Create(
"data",
"");
95 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
106 "build out | out.imp: cat in\n"));
108 Edge* edge = GetNode(
"out")->in_edge();
113 EXPECT_EQ(edge, GetNode(
"out.imp")->in_edge());
118 "build out | out.imp: cat in\n"));
119 fs_.Create(
"in",
"");
120 fs_.Create(
"out",
"");
123 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
132 "build out | out.imp: cat in\n"));
133 fs_.Create(
"out.imp",
"");
135 fs_.Create(
"in",
"");
136 fs_.Create(
"out",
"");
139 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out"), &err));
148 "build | out.imp: cat in\n"));
150 Edge* edge = GetNode(
"out.imp")->in_edge();
154 EXPECT_EQ(edge, GetNode(
"out.imp")->in_edge());
159 "build | out.imp: cat in\n"));
160 fs_.Create(
"in",
"");
163 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.imp"), &err));
171 "build | out.imp: cat in\n"));
172 fs_.Create(
"out.imp",
"");
174 fs_.Create(
"in",
"");
177 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.imp"), &err));
186 " depfile = $out.d\n" 187 " command = cat $in > $out\n" 188 "build ./out.o: catdep ./foo.cc\n"));
189 fs_.Create(
"foo.cc",
"");
190 fs_.Create(
"out.o.d",
"out.o: foo.cc\n");
191 fs_.Create(
"out.o",
"");
194 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
202 "build out1: cat in1\n" 203 "build mid1: cat in1\n" 204 "build out2: cat mid1\n" 205 "build out3 out4: cat mid1\n"));
208 vector<Node*> root_nodes = state_.RootNodes(&err);
210 for (
size_t i = 0; i < root_nodes.size(); ++i) {
211 string name = root_nodes[i]->path();
218 "build a$ b: cat no'space with$ space$$ no\"space2\n"));
220 Edge* edge = GetNode(
"a b")->in_edge();
222 EXPECT_EQ(
"cat no'space \"with space$\" \"no\\\"space2\" > \"a b\"",
225 EXPECT_EQ(
"cat 'no'\\''space' 'with space$' 'no\"space2' > 'a b'",
234 " depfile = $out.d\n" 235 " command = cat $in > $out\n" 236 "build ./out.o: catdep ./foo.cc\n"));
237 fs_.Create(
"foo.cc",
"");
238 fs_.Create(
"out.o.d",
"out.o: bar/../foo.cc\n");
239 fs_.Create(
"out.o",
"");
242 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
252 " depfile = $out.d\n" 253 " command = cat $in > $out\n" 254 "build ./out.o: catdep ./foo.cc\n"));
255 fs_.Create(
"foo.h",
"");
256 fs_.Create(
"foo.cc",
"");
258 fs_.Create(
"out.o.d",
"out.o: foo.h\n");
259 fs_.Create(
"out.o",
"");
262 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
267 fs_.RemoveFile(
"out.o.d");
268 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"out.o"), &err));
278 " command = depfile is $depfile\n" 279 "build out: r in\n"));
280 Edge* edge = GetNode(
"out")->in_edge();
289 " command = unused\n" 292 Edge* edge = GetNode(
"out")->in_edge();
301 " command = depfile is $depfile\n" 304 Edge* edge = GetNode(
"out")->in_edge();
312 "build n2: phony n1\n" 315 EXPECT_TRUE(scan_.RecomputeDirty(GetNode(
"n2"), &err));
330 "build a: phony a\n",
335 ASSERT_EQ(
"dependency cycle: a -> a [-w phonycycle=err]", err);
340 "build out: cat mid\n" 341 "build mid: cat in\n" 342 "build in: cat pre\n" 343 "build pre: cat out\n");
346 EXPECT_FALSE(scan_.RecomputeDirty(GetNode(
"out"), &err));
347 ASSERT_EQ(
"dependency cycle: out -> mid -> in -> pre -> out", err);
353 "build a b: cat a\n");
355 ASSERT_EQ(
"dependency cycle: a -> a", err);
361 "build b a: cat a\n"));
363 ASSERT_EQ(
"dependency cycle: a -> a", err);
370 "build c: cat a\n"));
372 ASSERT_EQ(
"dependency cycle: a -> c -> a", err);
382 "build f: cat e\n"));
384 ASSERT_EQ(
"dependency cycle: a -> d -> c -> b -> a", err);
393 " command = unused\n" 394 "build a b: deprule\n" 396 fs_.Create(
"dep.d",
"a: b\n");
400 ASSERT_EQ(
"dependency cycle: b -> b", err);
405 Edge* edge = GetNode(
"a")->in_edge();
415 " command = unused\n" 417 " command = unused\n" 418 "build a b: deprule\n" 421 fs_.Create(
"dep.d",
"a: c\n");
425 ASSERT_EQ(
"dependency cycle: b -> c -> b", err);
430 Edge* edge = GetNode(
"a")->in_edge();
441 " command = unused\n" 443 " command = unused\n" 444 "build a b: deprule\n" 448 fs_.Create(
"dep.d",
"a: c\n");
452 ASSERT_EQ(
"dependency cycle: b -> c -> b", err);
457 Edge* edge = GetNode(
"a")->in_edge();
465 "build out\\out1: cat src\\in1\n" 466 "build out\\out2/out3\\out4: cat mid1\n" 467 "build out3 out4\\foo: cat mid1\n"));
470 vector<Node*> root_nodes = state_.RootNodes(&err);
472 EXPECT_EQ(root_nodes[0]->path(),
"out/out1");
473 EXPECT_EQ(root_nodes[1]->path(),
"out/out2/out3/out4");
474 EXPECT_EQ(root_nodes[2]->path(),
"out3");
475 EXPECT_EQ(root_nodes[3]->path(),
"out4/foo");
476 EXPECT_EQ(root_nodes[0]->PathDecanonicalized(),
"out\\out1");
477 EXPECT_EQ(root_nodes[1]->PathDecanonicalized(),
"out\\out2/out3\\out4");
478 EXPECT_EQ(root_nodes[2]->PathDecanonicalized(),
"out3");
479 EXPECT_EQ(root_nodes[3]->PathDecanonicalized(),
"out4\\foo");
An implementation of DiskInterface that uses an in-memory representation of disk state.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
Plan stores the state of a build plan: what we intend to build, which steps we're ready to execute...
PhonyCycleAction phony_cycle_action_
bool AddTarget(Node *node, string *err)
Add a target to our plan (including all its dependencies).
int command_edge_count() const
Number of edges with commands to run.
An edge in the dependency graph; links between Nodes using Rules.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
A base test fixture that includes a State object with a builtin "cat" rule.
string GetBinding(const string &key)
Returns the shell-escaped value of |key|.
DependencyScan manages the process of scanning the files in a graph and updating the dirty/outputs_re...
#define ASSERT_NO_FATAL_FAILURE(a)
bool more_to_do() const
Returns true if there's more work to be done.
TEST_F(GraphTest, MissingImplicit)
vector< Node * > outputs_