Created
January 13, 2012 09:35
-
-
Save doctorlove/1605288 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -u -r -P ./mainline/src/build.cc ./patched/src/build.cc | |
--- ./mainline/src/build.cc 2011-08-22 16:04:17.684730100 +0200 | |
+++ ./patched/src/build.cc 2011-08-22 16:08:43.803459100 +0200 | |
@@ -22,6 +22,7 @@ | |
#include <sys/ioctl.h> | |
#include <sys/time.h> | |
#include <sys/termios.h> | |
+#include <errno.h> | |
#endif | |
#include "build_log.h" | |
@@ -321,7 +322,11 @@ | |
if ((*ni)->file_->mtime_ > most_recent_input) | |
most_recent_input = (*ni)->file_->mtime_; | |
string command = (*ei)->EvaluateCommand(); | |
- | |
+ if ((*ei)->HasRspFile()) | |
+ { | |
+ command += " " + (*ei)->GetRspFileContent(); | |
+ } | |
+ | |
// Now, recompute the dirty state of each output. | |
bool all_outputs_clean = true; | |
for (vector<Node*>::iterator ni = (*ei)->outputs_.begin(); | |
@@ -364,6 +369,36 @@ | |
printf("ready: %d\n", (int)ready_.size()); | |
} | |
+void CreateRspFile(const char * rspFileName, const char * rspFileContent) { | |
+ FILE * rspFile = fopen(rspFileName, "w"); | |
+ if (rspFile == NULL) { | |
+#ifdef _WIN32 | |
+ fprintf(stderr, "Unable to create rsp file %s\n", rspFileName); | |
+ Fatal("CreateRspFile : %s", GetLastErrorString().c_str()); | |
+#else | |
+ Fatal("Unable to create rsp file %s: %s\n", rspFileName, strerror( errno )); | |
+#endif | |
+ } | |
+ | |
+ if (fputs(rspFileContent, rspFile) == EOF) { | |
+#ifdef _WIN32 | |
+ fprintf(stderr, "Unable to write to the rsp file %s\n", rspFileName); | |
+ Fatal("CreateRspFile : %s", GetLastErrorString().c_str()); | |
+#else | |
+ Fatal("Unable to write the rsp file %s: %s\n", rspFileName, strerror( errno )); | |
+#endif | |
+ } | |
+ | |
+ if (fclose(rspFile) == EOF) { | |
+#ifdef _WIN32 | |
+ fprintf(stderr, "Unable to close the rsp file %s\n", rspFileName); | |
+ Fatal("CreateRspFile : %s", GetLastErrorString().c_str()); | |
+#else | |
+ Fatal("Unable to close the rsp file %s: %s\n", rspFileName, strerror( errno )); | |
+#endif | |
+ } | |
+} | |
+ | |
struct RealCommandRunner : public CommandRunner { | |
RealCommandRunner(const BuildConfig& config) : config_(config) {} | |
virtual ~RealCommandRunner() {} | |
@@ -380,8 +415,15 @@ | |
return ((int)subprocs_.running_.size()) < config_.parallelism; | |
} | |
-bool RealCommandRunner::StartCommand(Edge* edge) { | |
+bool RealCommandRunner::StartCommand(Edge* edge) { | |
+ // create a RSP file, if specified | |
+ if (edge->HasRspFile()) { | |
+ CreateRspFile(edge->GetRspFile().c_str(), edge->GetRspFileContent().c_str()); | |
+ } | |
+ | |
+ // run the command | |
string command = edge->EvaluateCommand(); | |
+ | |
Subprocess* subproc = new Subprocess; | |
subproc_to_edge_.insert(make_pair(subproc, edge)); | |
if (!subproc->Start(&subprocs_, command)) | |
diff -u -r -P ./mainline/src/build_log.cc ./patched/src/build_log.cc | |
--- ./mainline/src/build_log.cc 2011-08-22 15:20:37.451195100 +0200 | |
+++ ./patched/src/build_log.cc 2011-08-22 16:08:43.803459100 +0200 | |
@@ -89,6 +89,8 @@ | |
void BuildLog::RecordCommand(Edge* edge, int start_time, int end_time, | |
TimeStamp restat_mtime) { | |
- const string command = edge->EvaluateCommand(); | |
+ string command = edge->EvaluateCommand(); | |
+ if (edge->HasRspFile()) | |
+ command += " " + edge->GetRspFileContent(); | |
for (vector<Node*>::iterator out = edge->outputs_.begin(); | |
out != edge->outputs_.end(); ++out) { | |
const string& path = (*out)->path(); | |
diff -u -r -P ./mainline/src/clean.cc ./patched/src/clean.cc | |
--- ./mainline/src/clean.cc 2011-08-22 16:06:20.507324600 +0200 | |
+++ ./patched/src/clean.cc 2011-08-22 16:08:43.819059500 +0200 | |
@@ -115,6 +115,8 @@ | |
} | |
if (!(*e)->rule().depfile_.empty()) | |
Remove((*e)->EvaluateDepFile()); | |
+ if ((*e)->HasRspFile()) | |
+ Remove((*e)->GetRspFile()); | |
} | |
PrintFooter(); | |
return status_; | |
@@ -121,6 +121,11 @@ | |
void Cleaner::DoCleanTarget(Node* target) { | |
if (target->in_edge()) { | |
Remove(target->path()); | |
+ | |
+ if (target->in_edge()->HasRspFile()) { | |
+ Remove(target->in_edge()->GetRspFile()); | |
+ } | |
+ | |
for (vector<Node*>::iterator n = target->in_edge()->inputs_.begin(); | |
n != target->in_edge()->inputs_.end(); | |
++n) { | |
@@ -182,6 +187,10 @@ | |
out_node != (*e)->outputs_.end(); ++out_node) { | |
Remove((*out_node)->path()); | |
} | |
+ | |
+ if ((*e)->HasRspFile()) { | |
+ Remove((*e)->GetRspFile()); | |
+ } | |
} | |
} | |
} | |
diff -u -r -P ./mainline/src/clean_test.cc ./patched/src/clean_test.cc | |
--- ./mainline/src/clean_test.cc 2011-08-22 16:06:19.586901000 +0200 | |
+++ ./patched/src/clean_test.cc 2011-08-22 16:08:43.819059500 +0200 | |
@@ -249,6 +249,63 @@ | |
EXPECT_EQ(2u, fs_.files_removed_.size()); | |
} | |
+TEST_F(CleanTest, CleanRspFile) { | |
+ ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, | |
+"rule cc\n" | |
+" command = cc $in > $out\n" | |
+" rspfile = $rspfile\n" | |
+"build out1: cc in1\n" | |
+" rspfile = cc1.rsp\n")); | |
+ fs_.Create("out1", 1, ""); | |
+ fs_.Create("cc1.rsp", 1, ""); | |
+ | |
+ Cleaner cleaner(&state_, config_, &fs_); | |
+ EXPECT_EQ(0, cleaner.CleanAll()); | |
+ EXPECT_EQ(2, cleaner.cleaned_files_count()); | |
+ EXPECT_EQ(2u, fs_.files_removed_.size()); | |
+} | |
+ | |
+TEST_F(CleanTest, CleanRsp) { | |
+ ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, | |
+"rule cat_rsp \n" | |
+" command = cat $rspfile > $out\n" | |
+" rspfile = $rspfile\n" | |
+" rspfile_content = $in\n" | |
+"build in1: cat src1\n" | |
+"build out1: cat in1\n" | |
+"build in2: cat_rsp src2\n" | |
+" rspfile=in2.rsp\n" | |
+"build out2: cat_rsp in2\n" | |
+" rspfile=out2.rsp\n")); | |
+ fs_.Create("in1", 1, ""); | |
+ fs_.Create("out1", 1, ""); | |
+ fs_.Create("in2.rsp", 1, ""); | |
+ fs_.Create("out2.rsp", 1, ""); | |
+ fs_.Create("in2", 1, ""); | |
+ fs_.Create("out2", 1, ""); | |
+ | |
+ Cleaner cleaner(&state_, config_, &fs_); | |
+ ASSERT_EQ(0, cleaner.cleaned_files_count()); | |
+ ASSERT_EQ(0, cleaner.CleanTarget("out1")); | |
+ EXPECT_EQ(2, cleaner.cleaned_files_count()); | |
+ ASSERT_EQ(0, cleaner.CleanTarget("in2")); | |
+ EXPECT_EQ(2, cleaner.cleaned_files_count()); | |
+ ASSERT_EQ(0, cleaner.CleanRule("cat_rsp")); | |
+ EXPECT_EQ(2, cleaner.cleaned_files_count()); | |
+ | |
+ EXPECT_EQ(6u, fs_.files_removed_.size()); | |
+ | |
+ // Check they are removed. | |
+ EXPECT_EQ(0, fs_.Stat("in1")); | |
+ EXPECT_EQ(0, fs_.Stat("out1")); | |
+ EXPECT_EQ(0, fs_.Stat("in2")); | |
+ EXPECT_EQ(0, fs_.Stat("out2")); | |
+ EXPECT_EQ(0, fs_.Stat("in2.rsp")); | |
+ EXPECT_EQ(0, fs_.Stat("out2.rsp")); | |
+ | |
+ fs_.files_removed_.clear(); | |
+} | |
+ | |
TEST_F(CleanTest, CleanFailure) { | |
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, | |
"build dir: cat src1\n")); | |
diff -u -r -P ./mainline/src/graph.cc ./patched/src/graph.cc | |
--- ./mainline/src/graph.cc 2011-08-22 15:20:37.341992300 +0200 | |
+++ ./patched/src/graph.cc 2011-08-22 16:30:44.429976500 +0200 | |
@@ -75,6 +75,8 @@ | |
if (!dirty) { | |
BuildLog* build_log = state ? state->build_log_ : 0; | |
string command = EvaluateCommand(); | |
+ if (HasRspFile()) | |
+ command += " " + GetRspFileContent(); | |
for (vector<Node*>::iterator i = outputs_.begin(); | |
i != outputs_.end(); ++i) { | |
@@ -129,6 +131,20 @@ | |
return rule_->description_.Evaluate(&env); | |
} | |
+bool Edge::HasRspFile() { | |
+ return !rule_->rspfile_.empty(); | |
+} | |
+ | |
+string Edge::GetRspFile() { | |
+ EdgeEnv env(this); | |
+ return rule_->rspfile_.Evaluate(&env); | |
+} | |
+ | |
+string Edge::GetRspFileContent() { | |
+ EdgeEnv env(this); | |
+ return rule_->rspfile_content_.Evaluate(&env); | |
+} | |
+ | |
bool Edge::LoadDepFile(State* state, DiskInterface* disk_interface, | |
string* err) { | |
EdgeEnv env(this); | |
diff -u -r -P ./mainline/src/graph.h ./patched/src/graph.h | |
--- ./mainline/src/graph.h 2011-08-22 16:07:00.707566800 +0200 | |
+++ ./patched/src/graph.h 2011-08-22 16:08:43.834659900 +0200 | |
@@ -122,6 +122,8 @@ | |
EvalString command_; | |
EvalString description_; | |
EvalString depfile_; | |
+ EvalString rspfile_; | |
+ EvalString rspfile_content_; | |
}; | |
struct BuildLog; | |
@@ -85,6 +87,9 @@ | |
bool dirty, const string& command, Node* output); | |
string EvaluateCommand(); // XXX move to env, take env ptr | |
string GetDescription(); | |
+ bool HasRspFile(); | |
+ string GetRspFile(); | |
+ string GetRspFileContent(); | |
bool LoadDepFile(State* state, DiskInterface* disk_interface, string* err); | |
void Dump(); | |
diff -u -r -P ./mainline/src/parsers.cc ./patched/src/parsers.cc | |
--- ./mainline/src/parsers.cc 2011-08-22 15:20:37.341992300 +0200 | |
+++ ./patched/src/parsers.cc 2011-08-22 16:08:43.834659900 +0200 | |
@@ -116,6 +116,10 @@ | |
rule->generator_ = true; | |
} else if (key == "restat") { | |
rule->restat_ = true; | |
+ } else if (key == "rspfile") { | |
+ rule->rspfile_ = value; | |
+ } else if (key == "rspfile_content") { | |
+ rule->rspfile_content_ = value; | |
} else { | |
// Die on other keyvals for now; revisit if we want to add a | |
// scope here. | |
diff -u -r -P ./mainline/src/parsers_test.cc ./patched/src/parsers_test.cc | |
--- ./mainline/src/parsers_test.cc 2011-08-22 15:20:37.373193100 +0200 | |
+++ ./patched/src/parsers_test.cc 2011-08-22 16:08:43.850260300 +0200 | |
@@ -64,6 +64,24 @@ | |
EXPECT_EQ("cat $in > $out", rule->command().Serialize()); | |
} | |
+TEST_F(ParserTest, ResponseFiles) { | |
+ ASSERT_NO_FATAL_FAILURE(AssertParse( | |
+"rule cat_rsp\n" | |
+" command = cat $rspfile > $out\n" | |
+" rspfile = $rspfile\n" | |
+" rspfile_content = $in\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]", rule->rspfile_content_.Serialize()); | |
+} | |
+ | |
TEST_F(ParserTest, Variables) { | |
ASSERT_NO_FATAL_FAILURE(AssertParse( | |
"l = one-letter-test\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment