add $in_newline
authorScott Graham <scottmg@chromium.org>
Fri, 15 Jun 2012 21:48:43 +0000 (14:48 -0700)
committerScott Graham <scottmg@chromium.org>
Fri, 15 Jun 2012 21:48:43 +0000 (14:48 -0700)
doc/manual.asciidoc
src/graph.cc
src/parsers_test.cc

index 5de9638..e7983be 100644 (file)
@@ -359,9 +359,12 @@ command to run.  (In the context of a rule, the `command` variable is
 special and defines the command to run.  A full list of special
 variables is provided in <<ref_rule,the reference>>.)
 
-Within the context of a rule, two additional special variables are
+Within the context of a rule, three additional special variables are
 available: `$in` expands to the list of input files (`foo.c`) and
-`$out` to the output file (`foo.o`) for the command.
+`$out` to the output file (`foo.o`) for the command. For use with
+`$rspfile_content`, there is also `$in_newline`, which is the same as
+`$in`, except that multiple inputs are separated by `\n`, rather than
+spaces.
 
 
 Build statements
index f381d8a..5418ecf 100644 (file)
@@ -183,20 +183,23 @@ struct EdgeEnv : public Env {
   /// Given a span of Nodes, construct a list of paths suitable for a command
   /// line.  XXX here is where shell-escaping of e.g spaces should happen.
   string MakePathList(vector<Node*>::iterator begin,
-                      vector<Node*>::iterator end);
+                      vector<Node*>::iterator end,
+                      char sep);
 
   Edge* edge_;
 };
 
 string EdgeEnv::LookupVariable(const string& var) {
-  if (var == "in") {
+  if (var == "in" || var == "in_newline") {
     int explicit_deps_count = edge_->inputs_.size() - edge_->implicit_deps_ -
       edge_->order_only_deps_;
     return MakePathList(edge_->inputs_.begin(),
-                        edge_->inputs_.begin() + explicit_deps_count);
+                        edge_->inputs_.begin() + explicit_deps_count,
+                        var == "in" ? ' ' : '\n');
   } else if (var == "out") {
     return MakePathList(edge_->outputs_.begin(),
-                        edge_->outputs_.end());
+                        edge_->outputs_.end(),
+                        ' ');
   } else if (edge_->env_) {
     return edge_->env_->LookupVariable(var);
   } else {
@@ -206,11 +209,12 @@ string EdgeEnv::LookupVariable(const string& var) {
 }
 
 string EdgeEnv::MakePathList(vector<Node*>::iterator begin,
-                             vector<Node*>::iterator end) {
+                             vector<Node*>::iterator end,
+                             char sep) {
   string result;
   for (vector<Node*>::iterator i = begin; i != end; ++i) {
     if (!result.empty())
-      result.push_back(' ');
+      result.push_back(sep);
     const string& path = (*i)->path();
     if (path.find(" ") != string::npos) {
       result.append("\"");
index c5151b8..3cb16a7 100644 (file)
@@ -115,6 +115,24 @@ TEST_F(ParserTest, ResponseFiles) {
   EXPECT_EQ("[$in]", rule->rspfile_content().Serialize());
 }
 
+TEST_F(ParserTest, ResponseFilesInNewline) {
+  ASSERT_NO_FATAL_FAILURE(AssertParse(
+"rule cat_rsp\n"
+"  command = cat $rspfile > $out\n"
+"  rspfile = $rspfile\n"
+"  rspfile_content = $in_newline\n"
+"\n"
+"build out: cat_rsp in\n"
+"  rspfile=out.rsp\n"));
+
+  ASSERT_EQ(2u, state.rules_.size());
+  const Rule* rule = state.rules_.begin()->second;
+  EXPECT_EQ("cat_rsp", rule->name());
+  EXPECT_EQ("[cat ][$rspfile][ > ][$out]", rule->command().Serialize());
+  EXPECT_EQ("[$rspfile]", rule->rspfile().Serialize());
+  EXPECT_EQ("[$in_newline]", rule->rspfile_content().Serialize());
+}
+
 TEST_F(ParserTest, Variables) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(
 "l = one-letter-test\n"