blob: 4e5134949ea00c7d68f3ff9eae9199e864188538 [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
161 // If the latter rule has a command (regardless of the
162 // commands in oldRule), inputs in the latter rule has a
163 // priority.
164 if (rule.cmds.empty()) {
165 r->inputs = old_rule.inputs;
166 copy(rule.inputs.begin(), rule.inputs.end(),
167 back_inserter(r->inputs));
168 r->order_only_inputs = old_rule.order_only_inputs;
169 copy(rule.order_only_inputs.begin(), rule.order_only_inputs.end(),
170 back_inserter(r->order_only_inputs));
171 } else {
172 copy(old_rule.inputs.begin(), old_rule.inputs.end(),
173 back_inserter(r->inputs));
174 copy(old_rule.order_only_inputs.begin(),
175 old_rule.order_only_inputs.end(),
176 back_inserter(r->inputs));
177 }
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900178 for (StringPiece p : old_rule.output_patterns) {
179 r->output_patterns.push_back(p);
180 }
181 return r;
182 }
183
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900184 void PopulateExplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900185 for (StringPiece output : rule->outputs) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900186 const bool is_suffix_rule = PopulateSuffixRule(rule, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900187 auto p = rules_.insert(make_pair(output, rule));
188 if (p.second) {
189 if (!first_rule_ && output.get(0) != '.') {
190 first_rule_ = rule;
191 }
192 } else {
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900193 p.first->second =
194 MergeRules(*p.first->second, *rule, output, is_suffix_rule);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900195 }
196 }
197 }
198
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900199 void PopulateImplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900200 for (StringPiece output_pattern : rule->output_patterns) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900201 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900202 r->output_patterns.clear();
203 r->output_patterns.push_back(output_pattern);
204 implicit_rules_.push_back(r);
205 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900206 }
207
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900208 shared_ptr<Rule> LookupRule(StringPiece o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900209 auto found = rules_.find(o);
210 if (found != rules_.end())
211 return found->second;
212 return NULL;
213 }
214
215 Vars* LookupRuleVars(StringPiece o) {
216 auto found = rule_vars_.find(o);
217 if (found != rule_vars_.end())
218 return found->second;
219 return NULL;
220 }
221
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900222 bool CanPickImplicitRule(shared_ptr<Rule> rule, StringPiece output) {
223 CHECK(rule->output_patterns.size() == 1);
224 Pattern pat(rule->output_patterns[0]);
225 if (!pat.Match(output)) {
226 return false;
227 }
228 for (StringPiece input : rule->inputs) {
229 string buf;
230 pat.AppendSubst(output, input, &buf);
231 if (!Exists(buf))
232 return false;
233 }
234 return true;
235 }
236
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900237 Vars* MergeImplicitRuleVars(StringPiece output, Vars* vars) {
238 auto found = rule_vars_.find(output);
239 if (found == rule_vars_.end())
240 return vars;
241 if (vars == NULL)
242 return found->second;
243 // TODO: leak.
244 Vars* r = new Vars(*found->second);
245 for (auto p : *vars) {
246 (*r)[p.first] = p.second;
247 }
248 return r;
249 }
250
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900251 bool PickRule(StringPiece output,
252 shared_ptr<Rule>* out_rule, Vars** out_var) {
253 shared_ptr<Rule> rule = LookupRule(output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900254 Vars* vars = LookupRuleVars(output);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900255 *out_rule = rule;
256 *out_var = vars;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900257 if (rule) {
258 if (!rule->cmds.empty()) {
259 return true;
260 }
261 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900262
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900263 for (shared_ptr<Rule> irule : implicit_rules_) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900264 if (!CanPickImplicitRule(irule, output))
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900265 continue;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900266 if (rule) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900267 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900268 r->output_patterns = irule->output_patterns;
269 for (StringPiece input : irule->inputs)
270 r->inputs.push_back(input);
271 r->cmds = irule->cmds;
272 r->loc = irule->loc;
273 r->cmd_lineno = irule->cmd_lineno;
274 *out_rule = r;
275 return true;
276 }
277 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900278 CHECK(irule->output_patterns.size() == 1);
279 vars = MergeImplicitRuleVars(irule->output_patterns[0], vars);
280 *out_var = vars;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900281 }
282 *out_rule = irule;
283 return true;
284 }
285
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900286 StringPiece output_suffix = GetExt(output);
287 if (output_suffix.get(0) != '.')
288 return rule.get();
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900289 output_suffix = output_suffix.substr(1);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900290
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900291 SuffixRuleMap::const_iterator found = suffix_rules_.find(output_suffix);
292 if (found == suffix_rules_.end())
293 return rule.get();
294
295 for (shared_ptr<Rule> irule : found->second) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900296 CHECK(irule->inputs.size() == 1);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900297 StringPiece input = ReplaceSuffix(output, irule->inputs[0]);
298 if (!Exists(input))
299 continue;
300
301 if (rule) {
302 shared_ptr<Rule> r = make_shared<Rule>(*rule);
303 r->inputs.insert(r->inputs.begin(), input);
304 r->cmds = irule->cmds;
305 r->loc = irule->loc;
306 r->cmd_lineno = irule->cmd_lineno;
307 *out_rule = r;
308 return true;
309 }
310 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900311 CHECK(irule->outputs.size() == 1);
312 vars = MergeImplicitRuleVars(irule->outputs[0], vars);
313 *out_var = vars;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900314 }
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900315 *out_rule = irule;
316 return true;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900317 }
318
319 return rule.get();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900320 }
321
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900322 DepNode* BuildPlan(StringPiece output, StringPiece needed_by) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900323 LOG("BuildPlan: %s for %s",
324 output.as_string().c_str(),
325 needed_by.as_string().c_str());
326
327 auto found = done_.find(output);
328 if (found != done_.end()) {
329 return found->second;
330 }
331
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900332 DepNode* n = new DepNode(output, phony_.count(output));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900333 done_[output] = n;
334
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900335 shared_ptr<Rule> rule;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900336 Vars* vars;
337 if (!PickRule(output, &rule, &vars)) {
338 return n;
339 }
340
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900341 vector<unique_ptr<ScopedVar>> sv;
342 if (vars) {
343 for (const auto& p : *vars) {
344 StringPiece name = p.first;
345 RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
346 CHECK(var);
347 Var* new_var = var->v();
348 if (var->op() == AssignOp::PLUS_EQ) {
349 Var* old_var = ev_->LookupVar(name);
350 if (old_var->IsDefined()) {
351 // TODO: This would be incorrect and has a leak.
352 shared_ptr<string> s = make_shared<string>();
353 old_var->Eval(ev_, s.get());
Shinichiro Hamaji3c785c72015-06-23 19:22:34 +0900354 if (!s->empty())
355 *s += ' ';
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900356 new_var->Eval(ev_, s.get());
357 new_var = new SimpleVar(s, old_var->Origin());
358 }
359 } else if (var->op() == AssignOp::QUESTION_EQ) {
360 Var* old_var = ev_->LookupVar(name);
361 if (old_var->IsDefined()) {
362 continue;
363 }
364 }
365 sv.push_back(move(unique_ptr<ScopedVar>(
366 new ScopedVar(cur_rule_vars_.get(), name, new_var))));
367 }
368 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900369
370 for (StringPiece input : rule->inputs) {
371 if (rule->output_patterns.size() > 0) {
372 if (rule->output_patterns.size() > 1) {
373 ERROR("TODO: multiple output pattern is not supported yet");
374 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900375 string o;
Shinichiro Hamajia0560592015-06-24 17:14:28 +0900376 Pattern(rule->output_patterns[0]).AppendSubst(output, input, &o);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900377 input = Intern(o);
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900378 } else if (rule->is_suffix_rule) {
379 input = Intern(ReplaceSuffix(output, input));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900380 }
381
382 n->actual_inputs.push_back(input);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900383 DepNode* c = BuildPlan(input, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900384 n->deps.push_back(c);
385 }
386
Shinichiro Hamaji704e4fe2015-06-24 17:37:47 +0900387 for (StringPiece input : rule->order_only_inputs) {
388 DepNode* c = BuildPlan(input, output);
389 c->is_order_only = true;
390 n->deps.push_back(c);
391 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900392
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900393 n->has_rule = true;
394 n->cmds = rule->cmds;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900395 if (cur_rule_vars_->empty()) {
396 n->rule_vars = NULL;
397 } else {
398 n->rule_vars = new Vars;
399 for (auto p : *cur_rule_vars_) {
400 n->rule_vars->insert(p);
401 }
402 }
403 n->loc = rule->loc;
404 if (!rule->cmds.empty() && rule->cmd_lineno)
405 n->loc.lineno = rule->cmd_lineno;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900406
407 return n;
408 }
409
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900410 Evaluator* ev_;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900411 unordered_map<StringPiece, shared_ptr<Rule>> rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900412 const unordered_map<StringPiece, Vars*>& rule_vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900413 unique_ptr<Vars> cur_rule_vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900414
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900415 vector<shared_ptr<Rule>> implicit_rules_; // pattern=%. no prefix,suffix.
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900416 //vector<Rule*> iprefix_rules_; // pattern=prefix%.. may have suffix
417 //vector<Rule*> isuffix_rules_; // pattern=%suffix no prefix
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900418 typedef unordered_map<StringPiece, vector<shared_ptr<Rule>>> SuffixRuleMap;
419 SuffixRuleMap suffix_rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900420
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900421 shared_ptr<Rule> first_rule_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900422 unordered_map<StringPiece, DepNode*> done_;
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900423 unordered_set<StringPiece> phony_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900424};
425
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900426void MakeDep(Evaluator* ev,
427 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900428 const unordered_map<StringPiece, Vars*>& rule_vars,
429 const vector<StringPiece>& targets,
430 vector<DepNode*>* nodes) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900431 DepBuilder db(ev, rules, rule_vars);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900432 db.Build(targets, nodes);
433}
434
435void InitDepNodePool() {
436 g_dep_node_pool = new vector<DepNode*>;
437}
438
439void QuitDepNodePool() {
440 for (DepNode* n : *g_dep_node_pool)
441 delete n;
442 delete g_dep_node_pool;
443}