From ccaa3d1c9c8a581ce0cd696a3b0d6ab713908e40 Mon Sep 17 00:00:00 2001 From: Nicolas Despres Date: Tue, 24 May 2016 12:12:28 +0200 Subject: Parser accepts no explicit outputs. There is a class of commands that take an output directory where they create their output files. Among them are cp(1), tar(1) to name a few. These commands have one or more implicit outputs but no explicit output. With this patch, Ninja's parser accepts build edge with an empty list of explicit outputs. --- src/graph_test.cc | 39 +++++++++++++++++++++++++++++++++++++++ src/manifest_parser.cc | 10 +++++----- src/manifest_parser_test.cc | 5 +---- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/graph_test.cc b/src/graph_test.cc index 723e8ea..be08b19 100644 --- a/src/graph_test.cc +++ b/src/graph_test.cc @@ -149,6 +149,45 @@ TEST_F(GraphTest, ImplicitOutputOutOfDate) { EXPECT_TRUE(GetNode("out.imp")->dirty()); } +TEST_F(GraphTest, ImplicitOutputOnlyParse) { + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"build | out.imp: cat in\n")); + + Edge* edge = GetNode("out.imp")->in_edge(); + EXPECT_EQ(1, edge->outputs_.size()); + EXPECT_EQ("out.imp", edge->outputs_[0]->path()); + EXPECT_EQ(1, edge->implicit_outs_); + EXPECT_EQ(edge, GetNode("out.imp")->in_edge()); +} + +TEST_F(GraphTest, ImplicitOutputOnlyMissing) { + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"build | out.imp: cat in\n")); + fs_.Create("in", ""); + + Edge* edge = GetNode("out.imp")->in_edge(); + string err; + EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); + ASSERT_EQ("", err); + + EXPECT_TRUE(GetNode("out.imp")->dirty()); +} + +TEST_F(GraphTest, ImplicitOutputOnlyOutOfDate) { + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"build | out.imp: cat in\n")); + fs_.Create("out.imp", ""); + fs_.Tick(); + fs_.Create("in", ""); + + Edge* edge = GetNode("out.imp")->in_edge(); + string err; + EXPECT_TRUE(scan_.RecomputeDirty(edge, &err)); + ASSERT_EQ("", err); + + EXPECT_TRUE(GetNode("out.imp")->dirty()); +} + TEST_F(GraphTest, PathWithCurrentDirectory) { ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "rule catdep\n" diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc index a4f489e..d6dcf22 100644 --- a/src/manifest_parser.cc +++ b/src/manifest_parser.cc @@ -236,16 +236,13 @@ bool ManifestParser::ParseEdge(string* err) { EvalString out; if (!lexer_.ReadPath(&out, err)) return false; - if (out.empty()) - return lexer_.Error("expected path", err); - - do { + while (!out.empty()) { outs.push_back(out); out.Clear(); if (!lexer_.ReadPath(&out, err)) return false; - } while (!out.empty()); + } } // Add all implicit outs, counting how many as we go. @@ -262,6 +259,9 @@ bool ManifestParser::ParseEdge(string* err) { } } + if (outs.empty()) + return lexer_.Error("expected path", err); + if (!ExpectToken(Lexer::COLON, err)) return false; diff --git a/src/manifest_parser_test.cc b/src/manifest_parser_test.cc index 1312d26..3c82dc5 100644 --- a/src/manifest_parser_test.cc +++ b/src/manifest_parser_test.cc @@ -976,13 +976,10 @@ TEST_F(ParserTest, ImplicitOutputDupes) { TEST_F(ParserTest, NoExplicitOutput) { ManifestParser parser(&state, NULL, kDupeEdgeActionWarn); string err; - EXPECT_FALSE(parser.ParseTest( + EXPECT_TRUE(parser.ParseTest( "rule cat\n" " command = cat $in > $out\n" "build | imp : cat bar\n", &err)); - ASSERT_EQ("input:3: expected path\n" - "build | imp : cat bar\n" - " ^ near here", err); } TEST_F(ParserTest, DefaultDefault) { -- cgit v0.12