summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAsanka Herath <asanka@google.com>2017-01-09 19:52:54 (GMT)
committerAsanka Herath <asanka@google.com>2018-04-05 14:57:14 (GMT)
commitb6296fbde37c677654bfeb7c64515870d54457fb (patch)
tree27f039dbc62628c70ef7455e99f243c6667fde96 /src
parent4494d38c590ede0dd270fe247b2dae80d97fc855 (diff)
downloadNinja-b6296fbde37c677654bfeb7c64515870d54457fb.zip
Ninja-b6296fbde37c677654bfeb7c64515870d54457fb.tar.gz
Ninja-b6296fbde37c677654bfeb7c64515870d54457fb.tar.bz2
[compdb] Expand response files inline based on a switch.
References to response files in a clang compile_commands.json file can be tricky to deal with when tooling expects all the command flags to be present in the 'command' field. This change introduces a '-x' option to '-t compdb' that will expand @rspfile style response file invocations inline. E.g. ```sh $ ninja -t compdb cc [ { "directory": "/src/foo", "command": "cc -foo -bar @foo.obj.rsp", "file": "foo.cc" } ] $ ninja -t compdb -x cc [ { "directory": "/src/foo", "command": "cc -foo -bar foo.cc", "file": "foo.cc" } ] ```
Diffstat (limited to 'src')
-rw-r--r--src/ninja.cc62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/ninja.cc b/src/ninja.cc
index 245cac1..bc86456 100644
--- a/src/ninja.cc
+++ b/src/ninja.cc
@@ -662,10 +662,68 @@ void EncodeJSONString(const char *str) {
}
}
-int NinjaMain::ToolCompilationDatabase(const Options* options, int argc, char* argv[]) {
+enum EvaluateCommandMode {
+ ECM_NORMAL,
+ ECM_EXPAND_RSPFILE
+};
+string EvaluateCommandWithRspfile(Edge* edge, EvaluateCommandMode mode) {
+ string command = edge->EvaluateCommand();
+ if (mode == ECM_NORMAL)
+ return command;
+
+ string rspfile = edge->GetUnescapedRspfile();
+ if (rspfile.empty())
+ return command;
+
+ size_t index = command.find(rspfile);
+ if (index == 0 || index == string::npos || command[index - 1] != '@')
+ return command;
+
+ string rspfile_content = edge->GetBinding("rspfile_content");
+ size_t newline_index = 0;
+ while ((newline_index = rspfile_content.find('\n', newline_index)) !=
+ string::npos) {
+ rspfile_content.replace(newline_index, 1, 1, ' ');
+ ++newline_index;
+ }
+ command.replace(index - 1, rspfile.length() + 1, rspfile_content);
+ return command;
+}
+
+int NinjaMain::ToolCompilationDatabase(const Options* options, int argc,
+ char* argv[]) {
+ // The compdb tool uses getopt, and expects argv[0] to contain the name of
+ // the tool, i.e. "compdb".
+ argc++;
+ argv--;
+
bool first = true;
vector<char> cwd;
+ EvaluateCommandMode eval_mode = ECM_NORMAL;
+
+ optind = 1;
+ int opt;
+ while ((opt = getopt(argc, argv, const_cast<char*>("hx"))) != -1) {
+ switch(opt) {
+ case 'x':
+ eval_mode = ECM_EXPAND_RSPFILE;
+ break;
+
+ case 'h':
+ default:
+ printf(
+ "usage: ninja -t compdb [options] [rules]\n"
+ "\n"
+ "options:\n"
+ " -x expand @rspfile style response file invocations\n"
+ );
+ return 1;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
do {
cwd.resize(cwd.size() + 1024);
errno = 0;
@@ -688,7 +746,7 @@ int NinjaMain::ToolCompilationDatabase(const Options* options, int argc, char* a
printf("\n {\n \"directory\": \"");
EncodeJSONString(&cwd[0]);
printf("\",\n \"command\": \"");
- EncodeJSONString((*e)->EvaluateCommand().c_str());
+ EncodeJSONString(EvaluateCommandWithRspfile(*e, eval_mode).c_str());
printf("\",\n \"file\": \"");
EncodeJSONString((*e)->inputs_[0]->path().c_str());
printf("\",\n \"output\": \"");