summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2012-03-13 06:28:18 (GMT)
committerEvan Martin <martine@danga.com>2012-03-13 06:28:18 (GMT)
commiteca6bbe32bf3d1263ed1173a774f9d91c9b0f415 (patch)
treea8220600abd6f31fb3f9e7debc42b0c2589cc0f8
parentfffab7c868482cb8d24f40b42de958c074480226 (diff)
parent73af0ec4d0074ce1e9b1677b3525ed92f5fd00c7 (diff)
downloadNinja-eca6bbe32bf3d1263ed1173a774f9d91c9b0f415.zip
Ninja-eca6bbe32bf3d1263ed1173a774f9d91c9b0f415.tar.gz
Ninja-eca6bbe32bf3d1263ed1173a774f9d91c9b0f415.tar.bz2
Merge pull request #245 from usovalx/unify_depfile_targets
Issue #241 - handle depfiles generated by older versions of GCC
-rw-r--r--src/depfile_parser.cc16
-rw-r--r--src/depfile_parser.in.cc16
-rw-r--r--src/depfile_parser_test.cc17
3 files changed, 41 insertions, 8 deletions
diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc
index 8f8f9fe..7219eb0 100644
--- a/src/depfile_parser.cc
+++ b/src/depfile_parser.cc
@@ -32,8 +32,10 @@
bool DepfileParser::Parse(string* content, string* err) {
// in: current parser input point.
// end: end of input.
+ // parsing_targets: whether we are parsing targets or dependencies.
char* in = &(*content)[0];
char* end = in + content->size();
+ bool parsing_targets = true;
while (in < end) {
// out: current output point (typically same as in, but can fall behind
// as we de-escape backslashes).
@@ -180,16 +182,22 @@ yy13:
}
int len = out - filename;
- if (len > 0 && filename[len - 1] == ':')
+ const bool is_target = parsing_targets;
+ if (len > 0 && filename[len - 1] == ':') {
len--; // Strip off trailing colon, if any.
+ parsing_targets = false;
+ }
if (len == 0)
continue;
- if (!out_.str_) {
- out_ = StringPiece(filename, len);
- } else {
+ if (!is_target) {
ins_.push_back(StringPiece(filename, len));
+ } else if (!out_.str_) {
+ out_ = StringPiece(filename, len);
+ } else if (out_ != StringPiece(filename, len)) {
+ *err = "depfile has multiple output paths.";
+ return false;
}
}
return true;
diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc
index de1c38f..419ed8d 100644
--- a/src/depfile_parser.in.cc
+++ b/src/depfile_parser.in.cc
@@ -31,8 +31,10 @@
bool DepfileParser::Parse(string* content, string* err) {
// in: current parser input point.
// end: end of input.
+ // parsing_targets: whether we are parsing targets or dependencies.
char* in = &(*content)[0];
char* end = in + content->size();
+ bool parsing_targets = true;
while (in < end) {
// out: current output point (typically same as in, but can fall behind
// as we de-escape backslashes).
@@ -87,16 +89,22 @@ bool DepfileParser::Parse(string* content, string* err) {
}
int len = out - filename;
- if (len > 0 && filename[len - 1] == ':')
+ const bool is_target = parsing_targets;
+ if (len > 0 && filename[len - 1] == ':') {
len--; // Strip off trailing colon, if any.
+ parsing_targets = false;
+ }
if (len == 0)
continue;
- if (!out_.str_) {
- out_ = StringPiece(filename, len);
- } else {
+ if (!is_target) {
ins_.push_back(StringPiece(filename, len));
+ } else if (!out_.str_) {
+ out_ = StringPiece(filename, len);
+ } else if (out_ != StringPiece(filename, len)) {
+ *err = "depfile has multiple output paths.";
+ return false;
}
}
return true;
diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc
index 43e677c..883926a 100644
--- a/src/depfile_parser_test.cc
+++ b/src/depfile_parser_test.cc
@@ -102,3 +102,20 @@ TEST_F(DepfileParserTest, Escapes) {
parser_.out_.AsString());
ASSERT_EQ(0u, parser_.ins_.size());
}
+
+TEST_F(DepfileParserTest, UnifyMultupleOutputs) {
+ // check that multiple duplicate targets are properly unified
+ string err;
+ EXPECT_TRUE(Parse("foo foo: x y z", &err));
+ ASSERT_EQ(parser_.out_.AsString(), "foo");
+ ASSERT_EQ(parser_.ins_.size(), 3);
+ EXPECT_EQ("x", parser_.ins_[0].AsString());
+ EXPECT_EQ("y", parser_.ins_[1].AsString());
+ EXPECT_EQ("z", parser_.ins_[2].AsString());
+}
+
+TEST_F(DepfileParserTest, RejectMultipleDifferentOutputs) {
+ // check that multiple different outputs are rejected by the parser
+ string err;
+ EXPECT_FALSE(Parse("foo bar: x y z", &err));
+}