diff options
author | Nico Weber <thakis@chromium.org> | 2014-05-21 22:07:47 (GMT) |
---|---|---|
committer | Nico Weber <thakis@chromium.org> | 2014-05-21 22:18:01 (GMT) |
commit | bc239cca4f3f0757ba34d0306fbc2a2b75d067a2 (patch) | |
tree | e01abd5130c1e0f7ecca0dc0f0a24e8b9113dc0f /src/graph.cc | |
parent | 7103c32646df958b0287c65b1c660bf528a191d6 (diff) | |
download | Ninja-bc239cca4f3f0757ba34d0306fbc2a2b75d067a2.zip Ninja-bc239cca4f3f0757ba34d0306fbc2a2b75d067a2.tar.gz Ninja-bc239cca4f3f0757ba34d0306fbc2a2b75d067a2.tar.bz2 |
Make "depfile=$out.d" work if $out contains escaped characters, rspfile too.
Fixes #730. This has always been broken, but due to #690 more paths are now
escaped (e.g. paths containing + characters, like file.c++). Also see
discussion in #689.
The approach is to give EdgeEnv an enum deciding on whether or not to escape
file names, and provide functions that evaluate depfile and rspfile with that
set that to kNoEscape. (depfile=$out.d doesn't make sense on edges with
multiple outputs.)
This should be relatively safe, as $in and $out can't be used on edges, only
on rules (#687).
Diffstat (limited to 'src/graph.cc')
-rw-r--r-- | src/graph.cc | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/src/graph.cc b/src/graph.cc index 7121342..aa9c0e8 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -215,7 +215,10 @@ bool Edge::AllInputsReady() const { /// An Env for an Edge, providing $in and $out. struct EdgeEnv : public Env { - explicit EdgeEnv(Edge* edge) : edge_(edge) {} + enum EscapeKind { kShellEscape, kDoNotEscape }; + + explicit EdgeEnv(Edge* edge, EscapeKind escape) + : edge_(edge), escape_in_out_(escape) {} virtual string LookupVariable(const string& var); /// Given a span of Nodes, construct a list of paths suitable for a command @@ -225,6 +228,7 @@ struct EdgeEnv : public Env { char sep); Edge* edge_; + EscapeKind escape_in_out_; }; string EdgeEnv::LookupVariable(const string& var) { @@ -250,13 +254,18 @@ string EdgeEnv::MakePathList(vector<Node*>::iterator begin, char sep) { string result; for (vector<Node*>::iterator i = begin; i != end; ++i) { - if (!result.empty()) result.push_back(sep); + if (!result.empty()) + result.push_back(sep); const string& path = (*i)->path(); + if (escape_in_out_ == kShellEscape) { #if _WIN32 - GetWin32EscapedString(path, &result); + GetWin32EscapedString(path, &result); #else - GetShellEscapedString(path, &result); + GetShellEscapedString(path, &result); #endif + } else { + result.append(path); + } } return result; } @@ -272,7 +281,7 @@ string Edge::EvaluateCommand(bool incl_rsp_file) { } string Edge::GetBinding(const string& key) { - EdgeEnv env(this); + EdgeEnv env(this, EdgeEnv::kShellEscape); return env.LookupVariable(key); } @@ -280,6 +289,16 @@ bool Edge::GetBindingBool(const string& key) { return !GetBinding(key).empty(); } +string Edge::GetUnescapedDepfile() { + EdgeEnv env(this, EdgeEnv::kDoNotEscape); + return env.LookupVariable("depfile"); +} + +string Edge::GetUnescapedRspfile() { + EdgeEnv env(this, EdgeEnv::kDoNotEscape); + return env.LookupVariable("rspfile"); +} + void Edge::Dump(const char* prefix) const { printf("%s[ ", prefix); for (vector<Node*>::const_iterator i = inputs_.begin(); @@ -331,7 +350,7 @@ bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) { if (!deps_type.empty()) return LoadDepsFromLog(edge, err); - string depfile = edge->GetBinding("depfile"); + string depfile = edge->GetUnescapedDepfile(); if (!depfile.empty()) return LoadDepFile(edge, depfile, err); |