Skip to content

Commit 253e94c

Browse files
committed
v1.8.2
2 parents f69c785 + 87111bf commit 253e94c

14 files changed

+187
-66
lines changed

doc/manual.asciidoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The Ninja build system
22
======================
3-
v1.8.1, Sep 2017
3+
v1.8.2, Sep 2017
44

55

66
Introduction

src/build_log_perftest.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ bool WriteTestData(string* err) {
7171
long_rule_command += "$in -o $out\n";
7272

7373
State state;
74-
ManifestParser parser(&state, NULL, kDupeEdgeActionWarn);
74+
ManifestParser parser(&state, NULL);
7575
if (!parser.ParseTest("rule cxx\n command = " + long_rule_command, err))
7676
return false;
7777

src/build_test.cc

+13
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,19 @@ TEST_F(BuildTest, PhonyNoWork) {
10681068
EXPECT_TRUE(builder_.AlreadyUpToDate());
10691069
}
10701070

1071+
// Test a self-referencing phony. Ideally this should not work, but
1072+
// ninja 1.7 and below tolerated and CMake 2.8.12.x and 3.0.x both
1073+
// incorrectly produce it. We tolerate it for compatibility.
1074+
TEST_F(BuildTest, PhonySelfReference) {
1075+
string err;
1076+
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
1077+
"build a: phony a\n"));
1078+
1079+
EXPECT_TRUE(builder_.AddTarget("a", &err));
1080+
ASSERT_EQ("", err);
1081+
EXPECT_TRUE(builder_.AlreadyUpToDate());
1082+
}
1083+
10711084
TEST_F(BuildTest, Fail) {
10721085
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
10731086
"rule fail\n"

src/graph.cc

+15
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ bool DependencyScan::VerifyDAG(Node* node, vector<Node*>* stack, string* err) {
170170
err->append(" -> ");
171171
}
172172
err->append((*start)->path());
173+
174+
if ((start + 1) == stack->end() && edge->maybe_phonycycle_diagnostic()) {
175+
// The manifest parser would have filtered out the self-referencing
176+
// input if it were not configured to allow the error.
177+
err->append(" [-w phonycycle=err]");
178+
}
179+
173180
return false;
174181
}
175182

@@ -410,6 +417,14 @@ bool Edge::use_console() const {
410417
return pool() == &State::kConsolePool;
411418
}
412419

420+
bool Edge::maybe_phonycycle_diagnostic() const {
421+
// CMake 2.8.12.x and 3.0.x produced self-referencing phony rules
422+
// of the form "build a: phony ... a ...". Restrict our
423+
// "phonycycle" diagnostic option to the form it used.
424+
return is_phony() && outputs_.size() == 1 && implicit_outs_ == 0 &&
425+
implicit_deps_ == 0;
426+
}
427+
413428
// static
414429
string Node::PathDecanonicalized(const string& path, uint64_t slash_bits) {
415430
string result = path;

src/graph.h

+1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ struct Edge {
201201

202202
bool is_phony() const;
203203
bool use_console() const;
204+
bool maybe_phonycycle_diagnostic() const;
204205
};
205206

206207

src/graph_test.cc

+12
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,18 @@ TEST_F(GraphTest, NestedPhonyPrintsDone) {
323323
ASSERT_FALSE(plan_.more_to_do());
324324
}
325325

326+
TEST_F(GraphTest, PhonySelfReferenceError) {
327+
ManifestParserOptions parser_opts;
328+
parser_opts.phony_cycle_action_ = kPhonyCycleActionError;
329+
AssertParse(&state_,
330+
"build a: phony a\n",
331+
parser_opts);
332+
333+
string err;
334+
EXPECT_FALSE(scan_.RecomputeDirty(GetNode("a"), &err));
335+
ASSERT_EQ("dependency cycle: a -> a [-w phonycycle=err]", err);
336+
}
337+
326338
TEST_F(GraphTest, DependencyCycle) {
327339
AssertParse(&state_,
328340
"build out: cat mid\n"

src/manifest_parser.cc

+23-4
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
#include "version.h"
2727

2828
ManifestParser::ManifestParser(State* state, FileReader* file_reader,
29-
DupeEdgeAction dupe_edge_action)
29+
ManifestParserOptions options)
3030
: state_(state), file_reader_(file_reader),
31-
dupe_edge_action_(dupe_edge_action), quiet_(false) {
31+
options_(options), quiet_(false) {
3232
env_ = &state->bindings_;
3333
}
3434

@@ -346,7 +346,7 @@ bool ManifestParser::ParseEdge(string* err) {
346346
if (!CanonicalizePath(&path, &slash_bits, &path_err))
347347
return lexer_.Error(path_err, err);
348348
if (!state_->AddOut(edge, path, slash_bits)) {
349-
if (dupe_edge_action_ == kDupeEdgeActionError) {
349+
if (options_.dupe_edge_action_ == kDupeEdgeActionError) {
350350
lexer_.Error("multiple rules generate " + path + " [-w dupbuild=err]",
351351
err);
352352
return false;
@@ -383,6 +383,25 @@ bool ManifestParser::ParseEdge(string* err) {
383383
edge->implicit_deps_ = implicit;
384384
edge->order_only_deps_ = order_only;
385385

386+
if (options_.phony_cycle_action_ == kPhonyCycleActionWarn &&
387+
edge->maybe_phonycycle_diagnostic()) {
388+
// CMake 2.8.12.x and 3.0.x incorrectly write phony build statements
389+
// that reference themselves. Ninja used to tolerate these in the
390+
// build graph but that has since been fixed. Filter them out to
391+
// support users of those old CMake versions.
392+
Node* out = edge->outputs_[0];
393+
vector<Node*>::iterator new_end =
394+
remove(edge->inputs_.begin(), edge->inputs_.end(), out);
395+
if (new_end != edge->inputs_.end()) {
396+
edge->inputs_.erase(new_end, edge->inputs_.end());
397+
if (!quiet_) {
398+
Warning("phony target '%s' names itself as an input; "
399+
"ignoring [-w phonycycle=warn]",
400+
out->path().c_str());
401+
}
402+
}
403+
}
404+
386405
// Multiple outputs aren't (yet?) supported with depslog.
387406
string deps_type = edge->GetBinding("deps");
388407
if (!deps_type.empty() && edge->outputs_.size() > 1) {
@@ -400,7 +419,7 @@ bool ManifestParser::ParseFileInclude(bool new_scope, string* err) {
400419
return false;
401420
string path = eval.Evaluate(env_);
402421

403-
ManifestParser subparser(state_, file_reader_, dupe_edge_action_);
422+
ManifestParser subparser(state_, file_reader_, options_);
404423
if (new_scope) {
405424
subparser.env_ = new BindingEnv(env_);
406425
} else {

src/manifest_parser.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,23 @@ enum DupeEdgeAction {
3131
kDupeEdgeActionError,
3232
};
3333

34+
enum PhonyCycleAction {
35+
kPhonyCycleActionWarn,
36+
kPhonyCycleActionError,
37+
};
38+
39+
struct ManifestParserOptions {
40+
ManifestParserOptions()
41+
: dupe_edge_action_(kDupeEdgeActionWarn),
42+
phony_cycle_action_(kPhonyCycleActionWarn) {}
43+
DupeEdgeAction dupe_edge_action_;
44+
PhonyCycleAction phony_cycle_action_;
45+
};
46+
3447
/// Parses .ninja files.
3548
struct ManifestParser {
3649
ManifestParser(State* state, FileReader* file_reader,
37-
DupeEdgeAction dupe_edge_action);
50+
ManifestParserOptions options = ManifestParserOptions());
3851

3952
/// Load and parse a file.
4053
bool Load(const string& filename, string* err, Lexer* parent = NULL);
@@ -67,7 +80,7 @@ struct ManifestParser {
6780
BindingEnv* env_;
6881
FileReader* file_reader_;
6982
Lexer lexer_;
70-
DupeEdgeAction dupe_edge_action_;
83+
ManifestParserOptions options_;
7184
bool quiet_;
7285
};
7386

src/manifest_parser_perftest.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ int LoadManifests(bool measure_command_evaluation) {
5656
string err;
5757
RealDiskInterface disk_interface;
5858
State state;
59-
ManifestParser parser(&state, &disk_interface, kDupeEdgeActionWarn);
59+
ManifestParser parser(&state, &disk_interface);
6060
if (!parser.Load("build.ninja", &err)) {
6161
fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
6262
exit(1);

0 commit comments

Comments
 (0)