blob: 25a13daa5c81709c7c85c96db22ef9a0705f26f8 [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "dep.h"
18
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090019#include <algorithm>
Shinichiro Hamaji485f9122015-06-26 07:06:14 +090020#include <iterator>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090021#include <memory>
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +090022#include <unordered_map>
23#include <unordered_set>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090024
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090025#include "eval.h"
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090026#include "fileutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027#include "log.h"
28#include "rule.h"
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090029#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090030#include "var.h"
31
32static vector<DepNode*>* g_dep_node_pool;
33
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090034static StringPiece ReplaceSuffix(StringPiece s, StringPiece newsuf) {
35 string r;
36 AppendString(StripExt(s), &r);
37 r += '.';
38 AppendString(newsuf, &r);
39 return Intern(r);
40}
41
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090042DepNode::DepNode(StringPiece o, bool p)
43 : output(o),
44 has_rule(false),
45 is_order_only(false),
46 is_phony(p),
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090047 rule_vars(NULL) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090048 g_dep_node_pool->push_back(this);
49}
50
51class DepBuilder {
52 public:
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090053 DepBuilder(Evaluator* ev,
54 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090055 const unordered_map<StringPiece, Vars*>& rule_vars)
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090056 : ev_(ev),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090057 rule_vars_(rule_vars),
58 first_rule_(NULL) {
59 PopulateRules(rules);
60 }
61
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090062 ~DepBuilder() {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090063 }
64
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090065 void Build(vector<StringPiece> targets,
66 vector<DepNode*>* nodes) {
67 if (targets.empty()) {
68 if (!first_rule_) {
69 ERROR("*** No targets.");
70 }
71 CHECK(!first_rule_->outputs.empty());
72 targets.push_back(first_rule_->outputs[0]);
73 }
74
75 // TODO: LogStats?
76
77 for (StringPiece target : targets) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090078 cur_rule_vars_.reset(new Vars);
79 ev_->set_current_scope(cur_rule_vars_.get());
80 DepNode* n = BuildPlan(target, "");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090081 nodes->push_back(n);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090082 ev_->set_current_scope(NULL);
83 cur_rule_vars_.reset(NULL);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090084 }
85 }
86
87 private:
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +090088 bool Exists(StringPiece target) {
89 auto found = rules_.find(target);
90 if (found != rules_.end())
91 return true;
92 if (phony_.count(target))
93 return true;
94 return ::Exists(target);
95 }
96
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090097 void PopulateRules(const vector<shared_ptr<Rule>>& rules) {
98 for (shared_ptr<Rule> rule : rules) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090099 if (rule->outputs.empty()) {
100 PopulateImplicitRule(rule);
101 } else {
102 PopulateExplicitRule(rule);
103 }
104 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900105 reverse(implicit_rules_.begin(), implicit_rules_.end());
Shinichiro Hamaji65657d92015-06-24 17:05:50 +0900106 for (auto& p : suffix_rules_) {
107 reverse(p.second.begin(), p.second.end());
108 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900109 }
110
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900111 bool PopulateSuffixRule(shared_ptr<Rule> rule, StringPiece output) {
112 if (output.empty() || output[0] != '.')
113 return false;
114
115 StringPiece rest = output.substr(1);
116 size_t dot_index = rest.find('.');
117 // If there is only a single dot or the third dot, this is not a
118 // suffix rule.
119 if (dot_index == string::npos ||
120 rest.substr(dot_index+1).find('.') != string::npos) {
121 return false;
122 }
123
124 StringPiece input_suffix = rest.substr(0, dot_index);
125 StringPiece output_suffix = rest.substr(dot_index+1);
126 shared_ptr<Rule> r = make_shared<Rule>(*rule);
127 r->inputs.clear();
128 r->inputs.push_back(input_suffix);
129 r->is_suffix_rule = true;
130 suffix_rules_[output_suffix].push_back(r);
131 return true;
132 }
133
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900134 shared_ptr<Rule> MergeRules(const Rule& old_rule,
135 const Rule& rule,
136 StringPiece output,
137 bool is_suffix_rule) {
138 if (old_rule.is_double_colon != rule.is_double_colon) {
139 ERROR("%s:%d: *** target file `%s' has both : and :: entries.",
140 LOCF(rule.loc), output.as_string().c_str());
141 }
142 if (!old_rule.cmds.empty() && !rule.cmds.empty() &&
143 !is_suffix_rule && !rule.is_double_colon) {
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900144 WARN("%s:%d: warning: overriding commands for target `%s'",
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900145 LOCF(rule.cmd_loc()), output.as_string().c_str());
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900146 WARN("%s:%d: warning: ignoring old commands for target `%s'",
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900147 LOCF(old_rule.cmd_loc()), output.as_string().c_str());
148 }
149
150 shared_ptr<Rule> r = make_shared<Rule>(rule);
151 if (rule.is_double_colon) {
152 r->cmds.clear();
153 for (Value* c : old_rule.cmds)
154 r->cmds.push_back(c);
155 for (Value* c : rule.cmds)
156 r->cmds.push_back(c);
157 } else if (!old_rule.cmds.empty() && rule.cmds.empty()) {
158 r->cmds = old_rule.cmds;
159 }
Shinichiro Hamaji485f9122015-06-26 07:06:14 +0900160
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900161 // If the latter rule has a command (regardless of the commands in
162 // |old_rule|), inputs in the latter rule has a priority.
Shinichiro Hamaji485f9122015-06-26 07:06:14 +0900163 if (rule.cmds.empty()) {
164 r->inputs = old_rule.inputs;
165 copy(rule.inputs.begin(), rule.inputs.end(),
166 back_inserter(r->inputs));
167 r->order_only_inputs = old_rule.order_only_inputs;
168 copy(rule.order_only_inputs.begin(), rule.order_only_inputs.end(),
169 back_inserter(r->order_only_inputs));
170 } else {
171 copy(old_rule.inputs.begin(), old_rule.inputs.end(),
172 back_inserter(r->inputs));
173 copy(old_rule.order_only_inputs.begin(),
174 old_rule.order_only_inputs.end(),
175 back_inserter(r->inputs));
176 }
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900177 for (StringPiece p : old_rule.output_patterns) {
178 r->output_patterns.push_back(p);
179 }
180 return r;
181 }
182
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900183 void PopulateExplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900184 for (StringPiece output : rule->outputs) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900185 const bool is_suffix_rule = PopulateSuffixRule(rule, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900186 auto p = rules_.insert(make_pair(output, rule));
187 if (p.second) {
188 if (!first_rule_ && output.get(0) != '.') {
189 first_rule_ = rule;
190 }
191 } else {
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900192 p.first->second =
193 MergeRules(*p.first->second, *rule, output, is_suffix_rule);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900194 }
195 }
196 }
197
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900198 void PopulateImplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900199 for (StringPiece output_pattern : rule->output_patterns) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900200 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900201 r->output_patterns.clear();
202 r->output_patterns.push_back(output_pattern);
203 implicit_rules_.push_back(r);
204 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900205 }
206
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900207 shared_ptr<Rule> LookupRule(StringPiece o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900208 auto found = rules_.find(o);
209 if (found != rules_.end())
210 return found->second;
211 return NULL;
212 }
213
214 Vars* LookupRuleVars(StringPiece o) {
215 auto found = rule_vars_.find(o);
216 if (found != rule_vars_.end())
217 return found->second;
218 return NULL;
219 }
220
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900221 bool CanPickImplicitRule(shared_ptr<Rule> rule, StringPiece output) {
222 CHECK(rule->output_patterns.size() == 1);
223 Pattern pat(rule->output_patterns[0]);
224 if (!pat.Match(output)) {
225 return false;
226 }
227 for (StringPiece input : rule->inputs) {
228 string buf;
229 pat.AppendSubst(output, input, &buf);
230 if (!Exists(buf))
231 return false;
232 }
233 return true;
234 }
235
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900236 Vars* MergeImplicitRuleVars(StringPiece output, Vars* vars) {
237 auto found = rule_vars_.find(output);
238 if (found == rule_vars_.end())
239 return vars;
240 if (vars == NULL)
241 return found->second;
242 // TODO: leak.
243 Vars* r = new Vars(*found->second);
244 for (auto p : *vars) {
245 (*r)[p.first] = p.second;
246 }
247 return r;
248 }
249
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900250 bool PickRule(StringPiece output,
251 shared_ptr<Rule>* out_rule, Vars** out_var) {
252 shared_ptr<Rule> rule = LookupRule(output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900253 Vars* vars = LookupRuleVars(output);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900254 *out_rule = rule;
255 *out_var = vars;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900256 if (rule) {
257 if (!rule->cmds.empty()) {
258 return true;
259 }
260 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900261
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900262 for (shared_ptr<Rule> irule : implicit_rules_) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900263 if (!CanPickImplicitRule(irule, output))
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900264 continue;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900265 if (rule) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900266 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900267 r->output_patterns = irule->output_patterns;
Shinichiro Hamajid2c0fe12015-06-26 07:42:53 +0900268 r->inputs.clear();
269 r->inputs = irule->inputs;
270 copy(rule->inputs.begin(), rule->inputs.end(),
271 back_inserter(r->inputs));
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900272 r->cmds = irule->cmds;
273 r->loc = irule->loc;
274 r->cmd_lineno = irule->cmd_lineno;
275 *out_rule = r;
276 return true;
277 }
278 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900279 CHECK(irule->output_patterns.size() == 1);
280 vars = MergeImplicitRuleVars(irule->output_patterns[0], vars);
281 *out_var = vars;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900282 }
283 *out_rule = irule;
284 return true;
285 }
286
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900287 StringPiece output_suffix = GetExt(output);
288 if (output_suffix.get(0) != '.')
289 return rule.get();
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900290 output_suffix = output_suffix.substr(1);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900291
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900292 SuffixRuleMap::const_iterator found = suffix_rules_.find(output_suffix);
293 if (found == suffix_rules_.end())
294 return rule.get();
295
296 for (shared_ptr<Rule> irule : found->second) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900297 CHECK(irule->inputs.size() == 1);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900298 StringPiece input = ReplaceSuffix(output, irule->inputs[0]);
299 if (!Exists(input))
300 continue;
301
302 if (rule) {
303 shared_ptr<Rule> r = make_shared<Rule>(*rule);
304 r->inputs.insert(r->inputs.begin(), input);
305 r->cmds = irule->cmds;
306 r->loc = irule->loc;
307 r->cmd_lineno = irule->cmd_lineno;
308 *out_rule = r;
309 return true;
310 }
311 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900312 CHECK(irule->outputs.size() == 1);
313 vars = MergeImplicitRuleVars(irule->outputs[0], vars);
314 *out_var = vars;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900315 }
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900316 *out_rule = irule;
317 return true;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900318 }
319
320 return rule.get();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900321 }
322
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900323 DepNode* BuildPlan(StringPiece output, StringPiece needed_by) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900324 LOG("BuildPlan: %s for %s",
325 output.as_string().c_str(),
326 needed_by.as_string().c_str());
327
328 auto found = done_.find(output);
329 if (found != done_.end()) {
330 return found->second;
331 }
332
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900333 DepNode* n = new DepNode(output, phony_.count(output));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900334 done_[output] = n;
335
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900336 shared_ptr<Rule> rule;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900337 Vars* vars;
338 if (!PickRule(output, &rule, &vars)) {
339 return n;
340 }
341
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900342 vector<unique_ptr<ScopedVar>> sv;
343 if (vars) {
344 for (const auto& p : *vars) {
345 StringPiece name = p.first;
346 RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
347 CHECK(var);
348 Var* new_var = var->v();
349 if (var->op() == AssignOp::PLUS_EQ) {
350 Var* old_var = ev_->LookupVar(name);
351 if (old_var->IsDefined()) {
352 // TODO: This would be incorrect and has a leak.
353 shared_ptr<string> s = make_shared<string>();
354 old_var->Eval(ev_, s.get());
Shinichiro Hamaji3c785c72015-06-23 19:22:34 +0900355 if (!s->empty())
356 *s += ' ';
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900357 new_var->Eval(ev_, s.get());
358 new_var = new SimpleVar(s, old_var->Origin());
359 }
360 } else if (var->op() == AssignOp::QUESTION_EQ) {
361 Var* old_var = ev_->LookupVar(name);
362 if (old_var->IsDefined()) {
363 continue;
364 }
365 }
366 sv.push_back(move(unique_ptr<ScopedVar>(
367 new ScopedVar(cur_rule_vars_.get(), name, new_var))));
368 }
369 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900370
371 for (StringPiece input : rule->inputs) {
372 if (rule->output_patterns.size() > 0) {
373 if (rule->output_patterns.size() > 1) {
374 ERROR("TODO: multiple output pattern is not supported yet");
375 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900376 string o;
Shinichiro Hamajia0560592015-06-24 17:14:28 +0900377 Pattern(rule->output_patterns[0]).AppendSubst(output, input, &o);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900378 input = Intern(o);
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900379 } else if (rule->is_suffix_rule) {
380 input = Intern(ReplaceSuffix(output, input));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900381 }
382
383 n->actual_inputs.push_back(input);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900384 DepNode* c = BuildPlan(input, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900385 n->deps.push_back(c);
386 }
387
Shinichiro Hamaji704e4fe2015-06-24 17:37:47 +0900388 for (StringPiece input : rule->order_only_inputs) {
389 DepNode* c = BuildPlan(input, output);
390 c->is_order_only = true;
391 n->deps.push_back(c);
392 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900393
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900394 n->has_rule = true;
395 n->cmds = rule->cmds;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900396 if (cur_rule_vars_->empty()) {
397 n->rule_vars = NULL;
398 } else {
399 n->rule_vars = new Vars;
400 for (auto p : *cur_rule_vars_) {
401 n->rule_vars->insert(p);
402 }
403 }
404 n->loc = rule->loc;
405 if (!rule->cmds.empty() && rule->cmd_lineno)
406 n->loc.lineno = rule->cmd_lineno;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900407
408 return n;
409 }
410
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900411 Evaluator* ev_;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900412 unordered_map<StringPiece, shared_ptr<Rule>> rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900413 const unordered_map<StringPiece, Vars*>& rule_vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900414 unique_ptr<Vars> cur_rule_vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900415
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900416 vector<shared_ptr<Rule>> implicit_rules_; // pattern=%. no prefix,suffix.
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900417 //vector<Rule*> iprefix_rules_; // pattern=prefix%.. may have suffix
418 //vector<Rule*> isuffix_rules_; // pattern=%suffix no prefix
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900419 typedef unordered_map<StringPiece, vector<shared_ptr<Rule>>> SuffixRuleMap;
420 SuffixRuleMap suffix_rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900421
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900422 shared_ptr<Rule> first_rule_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900423 unordered_map<StringPiece, DepNode*> done_;
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900424 unordered_set<StringPiece> phony_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900425};
426
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900427void MakeDep(Evaluator* ev,
428 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900429 const unordered_map<StringPiece, Vars*>& rule_vars,
430 const vector<StringPiece>& targets,
431 vector<DepNode*>* nodes) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900432 DepBuilder db(ev, rules, rule_vars);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900433 db.Build(targets, nodes);
434}
435
436void InitDepNodePool() {
437 g_dep_node_pool = new vector<DepNode*>;
438}
439
440void QuitDepNodePool() {
441 for (DepNode* n : *g_dep_node_pool)
442 delete n;
443 delete g_dep_node_pool;
444}