Skip to content

Instantly share code, notes, and snippets.

@doctorlove
Created January 13, 2012 09:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doctorlove/1605288 to your computer and use it in GitHub Desktop.
Save doctorlove/1605288 to your computer and use it in GitHub Desktop.
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