blob: c35df36d551db4d37929139f0cd8c8eaec4a0a72 [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
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090015#include "dep.h"
16
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090017#include <algorithm>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090018#include <memory>
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +090019#include <unordered_map>
20#include <unordered_set>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090021
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090022#include "eval.h"
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090023#include "fileutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090024#include "log.h"
25#include "rule.h"
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090026#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027#include "var.h"
28
29static vector<DepNode*>* g_dep_node_pool;
30
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090031static StringPiece ReplaceSuffix(StringPiece s, StringPiece newsuf) {
32 string r;
33 AppendString(StripExt(s), &r);
34 r += '.';
35 AppendString(newsuf, &r);
36 return Intern(r);
37}
38
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090039DepNode::DepNode(StringPiece o, bool p)
40 : output(o),
41 has_rule(false),
42 is_order_only(false),
43 is_phony(p),
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090044 rule_vars(NULL) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090045 g_dep_node_pool->push_back(this);
46}
47
48class DepBuilder {
49 public:
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090050 DepBuilder(Evaluator* ev,
51 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090052 const unordered_map<StringPiece, Vars*>& rule_vars)
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090053 : ev_(ev),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090054 rule_vars_(rule_vars),
55 first_rule_(NULL) {
56 PopulateRules(rules);
57 }
58
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090059 ~DepBuilder() {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090060 }
61
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090062 void Build(vector<StringPiece> targets,
63 vector<DepNode*>* nodes) {
64 if (targets.empty()) {
65 if (!first_rule_) {
66 ERROR("*** No targets.");
67 }
68 CHECK(!first_rule_->outputs.empty());
69 targets.push_back(first_rule_->outputs[0]);
70 }
71
72 // TODO: LogStats?
73
74 for (StringPiece target : targets) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090075 cur_rule_vars_.reset(new Vars);
76 ev_->set_current_scope(cur_rule_vars_.get());
77 DepNode* n = BuildPlan(target, "");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090078 nodes->push_back(n);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090079 ev_->set_current_scope(NULL);
80 cur_rule_vars_.reset(NULL);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090081 }
82 }
83
84 private:
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +090085 bool Exists(StringPiece target) {
86 auto found = rules_.find(target);
87 if (found != rules_.end())
88 return true;
89 if (phony_.count(target))
90 return true;
91 return ::Exists(target);
92 }
93
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090094 void PopulateRules(const vector<shared_ptr<Rule>>& rules) {
95 for (shared_ptr<Rule> rule : rules) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090096 if (rule->outputs.empty()) {
97 PopulateImplicitRule(rule);
98 } else {
99 PopulateExplicitRule(rule);
100 }
101 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900102 reverse(implicit_rules_.begin(), implicit_rules_.end());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900103 }
104
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900105 bool PopulateSuffixRule(shared_ptr<Rule> rule, StringPiece output) {
106 if (output.empty() || output[0] != '.')
107 return false;
108
109 StringPiece rest = output.substr(1);
110 size_t dot_index = rest.find('.');
111 // If there is only a single dot or the third dot, this is not a
112 // suffix rule.
113 if (dot_index == string::npos ||
114 rest.substr(dot_index+1).find('.') != string::npos) {
115 return false;
116 }
117
118 StringPiece input_suffix = rest.substr(0, dot_index);
119 StringPiece output_suffix = rest.substr(dot_index+1);
120 shared_ptr<Rule> r = make_shared<Rule>(*rule);
121 r->inputs.clear();
122 r->inputs.push_back(input_suffix);
123 r->is_suffix_rule = true;
124 suffix_rules_[output_suffix].push_back(r);
125 return true;
126 }
127
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900128 shared_ptr<Rule> MergeRules(const Rule& old_rule,
129 const Rule& rule,
130 StringPiece output,
131 bool is_suffix_rule) {
132 if (old_rule.is_double_colon != rule.is_double_colon) {
133 ERROR("%s:%d: *** target file `%s' has both : and :: entries.",
134 LOCF(rule.loc), output.as_string().c_str());
135 }
136 if (!old_rule.cmds.empty() && !rule.cmds.empty() &&
137 !is_suffix_rule && !rule.is_double_colon) {
138 WARN("%s:%d: overriding commands for target `%s'",
139 LOCF(rule.cmd_loc()), output.as_string().c_str());
140 WARN("%s:%d: ignoring old commands for target `%s'",
141 LOCF(old_rule.cmd_loc()), output.as_string().c_str());
142 }
143
144 shared_ptr<Rule> r = make_shared<Rule>(rule);
145 if (rule.is_double_colon) {
146 r->cmds.clear();
147 for (Value* c : old_rule.cmds)
148 r->cmds.push_back(c);
149 for (Value* c : rule.cmds)
150 r->cmds.push_back(c);
151 } else if (!old_rule.cmds.empty() && rule.cmds.empty()) {
152 r->cmds = old_rule.cmds;
153 }
154 for (StringPiece p : old_rule.output_patterns) {
155 r->output_patterns.push_back(p);
156 }
157 return r;
158 }
159
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900160 void PopulateExplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900161 for (StringPiece output : rule->outputs) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900162 const bool is_suffix_rule = PopulateSuffixRule(rule, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900163 auto p = rules_.insert(make_pair(output, rule));
164 if (p.second) {
165 if (!first_rule_ && output.get(0) != '.') {
166 first_rule_ = rule;
167 }
168 } else {
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900169 p.first->second =
170 MergeRules(*p.first->second, *rule, output, is_suffix_rule);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900171 }
172 }
173 }
174
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900175 void PopulateImplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900176 for (StringPiece output_pattern : rule->output_patterns) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900177 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900178 r->output_patterns.clear();
179 r->output_patterns.push_back(output_pattern);
180 implicit_rules_.push_back(r);
181 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900182 }
183
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900184 shared_ptr<Rule> LookupRule(StringPiece o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900185 auto found = rules_.find(o);
186 if (found != rules_.end())
187 return found->second;
188 return NULL;
189 }
190
191 Vars* LookupRuleVars(StringPiece o) {
192 auto found = rule_vars_.find(o);
193 if (found != rule_vars_.end())
194 return found->second;
195 return NULL;
196 }
197
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900198 bool CanPickImplicitRule(shared_ptr<Rule> rule, StringPiece output) {
199 CHECK(rule->output_patterns.size() == 1);
200 Pattern pat(rule->output_patterns[0]);
201 if (!pat.Match(output)) {
202 return false;
203 }
204 for (StringPiece input : rule->inputs) {
205 string buf;
206 pat.AppendSubst(output, input, &buf);
207 if (!Exists(buf))
208 return false;
209 }
210 return true;
211 }
212
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900213 bool PickRule(StringPiece output,
214 shared_ptr<Rule>* out_rule, Vars** out_var) {
215 shared_ptr<Rule> rule = LookupRule(output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900216 Vars* vars = LookupRuleVars(output);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900217 *out_rule = rule;
218 *out_var = vars;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900219 if (rule) {
220 if (!rule->cmds.empty()) {
221 return true;
222 }
223 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900224
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900225 for (shared_ptr<Rule> irule : implicit_rules_) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900226 if (!CanPickImplicitRule(irule, output))
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900227 continue;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900228 if (rule) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900229 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900230 r->output_patterns = irule->output_patterns;
231 for (StringPiece input : irule->inputs)
232 r->inputs.push_back(input);
233 r->cmds = irule->cmds;
234 r->loc = irule->loc;
235 r->cmd_lineno = irule->cmd_lineno;
236 *out_rule = r;
237 return true;
238 }
239 if (vars) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900240 // TODO: Merge implicit variables...
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900241 CHECK(false);
242 }
243 *out_rule = irule;
244 return true;
245 }
246
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900247 StringPiece output_suffix = GetExt(output);
248 if (output_suffix.get(0) != '.')
249 return rule.get();
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900250 output_suffix = output_suffix.substr(1);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900251
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900252 SuffixRuleMap::const_iterator found = suffix_rules_.find(output_suffix);
253 if (found == suffix_rules_.end())
254 return rule.get();
255
256 for (shared_ptr<Rule> irule : found->second) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900257 CHECK(irule->inputs.size() == 1);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900258 StringPiece input = ReplaceSuffix(output, irule->inputs[0]);
259 if (!Exists(input))
260 continue;
261
262 if (rule) {
263 shared_ptr<Rule> r = make_shared<Rule>(*rule);
264 r->inputs.insert(r->inputs.begin(), input);
265 r->cmds = irule->cmds;
266 r->loc = irule->loc;
267 r->cmd_lineno = irule->cmd_lineno;
268 *out_rule = r;
269 return true;
270 }
271 if (vars) {
272 // TODO: Merge implicit variables...
273 CHECK(false);
274 }
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900275 *out_rule = irule;
276 return true;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900277 }
278
279 return rule.get();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900280 }
281
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900282 DepNode* BuildPlan(StringPiece output, StringPiece needed_by) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900283 LOG("BuildPlan: %s for %s",
284 output.as_string().c_str(),
285 needed_by.as_string().c_str());
286
287 auto found = done_.find(output);
288 if (found != done_.end()) {
289 return found->second;
290 }
291
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900292 DepNode* n = new DepNode(output, phony_.count(output));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900293 done_[output] = n;
294
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900295 shared_ptr<Rule> rule;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900296 Vars* vars;
297 if (!PickRule(output, &rule, &vars)) {
298 return n;
299 }
300
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900301 vector<unique_ptr<ScopedVar>> sv;
302 if (vars) {
303 for (const auto& p : *vars) {
304 StringPiece name = p.first;
305 RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
306 CHECK(var);
307 Var* new_var = var->v();
308 if (var->op() == AssignOp::PLUS_EQ) {
309 Var* old_var = ev_->LookupVar(name);
310 if (old_var->IsDefined()) {
311 // TODO: This would be incorrect and has a leak.
312 shared_ptr<string> s = make_shared<string>();
313 old_var->Eval(ev_, s.get());
314 *s += ' ';
315 new_var->Eval(ev_, s.get());
316 new_var = new SimpleVar(s, old_var->Origin());
317 }
318 } else if (var->op() == AssignOp::QUESTION_EQ) {
319 Var* old_var = ev_->LookupVar(name);
320 if (old_var->IsDefined()) {
321 continue;
322 }
323 }
324 sv.push_back(move(unique_ptr<ScopedVar>(
325 new ScopedVar(cur_rule_vars_.get(), name, new_var))));
326 }
327 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900328
329 for (StringPiece input : rule->inputs) {
330 if (rule->output_patterns.size() > 0) {
331 if (rule->output_patterns.size() > 1) {
332 ERROR("TODO: multiple output pattern is not supported yet");
333 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900334 string o;
335 Pattern(rule->output_patterns[0]).AppendSubst(input, output, &o);
336 input = Intern(o);
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900337 } else if (rule->is_suffix_rule) {
338 input = Intern(ReplaceSuffix(output, input));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900339 }
340
341 n->actual_inputs.push_back(input);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900342 DepNode* c = BuildPlan(input, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900343 n->deps.push_back(c);
344 }
345
346 // TODO: order only
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900347
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900348 n->has_rule = true;
349 n->cmds = rule->cmds;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900350 if (cur_rule_vars_->empty()) {
351 n->rule_vars = NULL;
352 } else {
353 n->rule_vars = new Vars;
354 for (auto p : *cur_rule_vars_) {
355 n->rule_vars->insert(p);
356 }
357 }
358 n->loc = rule->loc;
359 if (!rule->cmds.empty() && rule->cmd_lineno)
360 n->loc.lineno = rule->cmd_lineno;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900361
362 return n;
363 }
364
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900365 Evaluator* ev_;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900366 unordered_map<StringPiece, shared_ptr<Rule>> rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900367 const unordered_map<StringPiece, Vars*>& rule_vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900368 unique_ptr<Vars> cur_rule_vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900369
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900370 vector<shared_ptr<Rule>> implicit_rules_; // pattern=%. no prefix,suffix.
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900371 //vector<Rule*> iprefix_rules_; // pattern=prefix%.. may have suffix
372 //vector<Rule*> isuffix_rules_; // pattern=%suffix no prefix
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900373 typedef unordered_map<StringPiece, vector<shared_ptr<Rule>>> SuffixRuleMap;
374 SuffixRuleMap suffix_rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900375
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900376 shared_ptr<Rule> first_rule_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900377 unordered_map<StringPiece, DepNode*> done_;
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900378 unordered_set<StringPiece> phony_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900379};
380
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900381void MakeDep(Evaluator* ev,
382 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900383 const unordered_map<StringPiece, Vars*>& rule_vars,
384 const vector<StringPiece>& targets,
385 vector<DepNode*>* nodes) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900386 DepBuilder db(ev, rules, rule_vars);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900387 db.Build(targets, nodes);
388}
389
390void InitDepNodePool() {
391 g_dep_node_pool = new vector<DepNode*>;
392}
393
394void QuitDepNodePool() {
395 for (DepNode* n : *g_dep_node_pool)
396 delete n;
397 delete g_dep_node_pool;
398}