diff options
author | Asanka Herath <asanka@google.com> | 2017-01-09 19:52:54 (GMT) |
---|---|---|
committer | Asanka Herath <asanka@google.com> | 2018-04-05 14:57:14 (GMT) |
commit | b6296fbde37c677654bfeb7c64515870d54457fb (patch) | |
tree | 27f039dbc62628c70ef7455e99f243c6667fde96 /src | |
parent | 4494d38c590ede0dd270fe247b2dae80d97fc855 (diff) | |
download | Ninja-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.cc | 62 |
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\": \""); |