blob: d2d45af1db6c4c9eb566324937645b143d60a556 [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 Hamajie7992752015-06-29 18:38:35 +090030#include "symtab.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090031#include "var.h"
32
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090033namespace {
34
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090035static vector<DepNode*>* g_dep_node_pool;
36
Shinichiro Hamajie7992752015-06-29 18:38:35 +090037static Symbol ReplaceSuffix(Symbol s, Symbol newsuf) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090038 string r;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090039 AppendString(StripExt(s.str()), &r);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090040 r += '.';
Shinichiro Hamajie7992752015-06-29 18:38:35 +090041 AppendString(newsuf.str(), &r);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090042 return Intern(r);
43}
44
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090045class RuleTrie {
46 struct Entry {
47 Entry(shared_ptr<Rule> r, StringPiece s)
48 : rule(r), suffix(s) {
49 }
50 shared_ptr<Rule> rule;
51 StringPiece suffix;
52 };
53
54 public:
55 RuleTrie() {}
56 ~RuleTrie() {
57 for (auto& p : children_)
58 delete p.second;
59 }
60
61 void Add(StringPiece name, shared_ptr<Rule> rule) {
62 if (name.empty() || name[0] == '%') {
63 rules_.push_back(Entry(rule, name));
64 return;
65 }
66 const char c = name[0];
67 auto p = children_.emplace(c, nullptr);
68 if (p.second) {
69 p.first->second = new RuleTrie();
70 }
71 p.first->second->Add(name.substr(1), rule);
72 }
73
Shinichiro Hamajif772b172015-06-29 16:05:44 +090074 void Get(StringPiece name, vector<shared_ptr<Rule>>* rules) const {
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090075 for (const Entry& ent : rules_) {
76 if ((ent.suffix.empty() && name.empty()) ||
77 HasSuffix(name, ent.suffix.substr(1))) {
78 rules->push_back(ent.rule);
79 }
80 }
Shinichiro Hamajif772b172015-06-29 16:05:44 +090081 if (name.empty())
82 return;
83 auto found = children_.find(name[0]);
84 if (found != children_.end()) {
85 found->second->Get(name.substr(1), rules);
86 }
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090087 }
88
89 size_t size() const {
90 size_t r = rules_.size();
91 for (const auto& c : children_)
92 r += c.second->size();
93 return r;
94 }
95
96 private:
97 vector<Entry> rules_;
98 unordered_map<char, RuleTrie*> children_;
99};
100
101} // namespace
102
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900103DepNode::DepNode(Symbol o, bool p)
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900104 : output(o),
105 has_rule(false),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900106 is_phony(p),
Colin Cross5b26db32015-09-29 16:51:02 -0700107 is_default_target(false),
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +0900108 rule_vars(NULL),
109 output_pattern(Symbol::IsUninitialized()) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900110 g_dep_node_pool->push_back(this);
111}
112
113class DepBuilder {
114 public:
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900115 DepBuilder(Evaluator* ev,
116 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900117 const unordered_map<Symbol, Vars*>& rule_vars)
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900118 : ev_(ev),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900119 rule_vars_(rule_vars),
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900120 implicit_rules_(new RuleTrie()),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900121 first_rule_(NULL) {
122 PopulateRules(rules);
Shinichiro Hamajib4969af2015-06-28 02:06:54 +0900123 LOG_STAT("%zu variables", ev->mutable_vars()->size());
124 LOG_STAT("%zu explicit rules", rules_.size());
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900125 LOG_STAT("%zu implicit rules", implicit_rules_->size());
Shinichiro Hamajib4969af2015-06-28 02:06:54 +0900126 LOG_STAT("%zu suffix rules", suffix_rules_.size());
Shinichiro Hamajid40b6fe2015-06-29 17:08:42 +0900127
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900128 auto found = rules_.find(Intern(".PHONY"));
Shinichiro Hamajid40b6fe2015-06-29 17:08:42 +0900129 if (found != rules_.end()) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900130 for (Symbol input : found->second->inputs) {
Shinichiro Hamajid40b6fe2015-06-29 17:08:42 +0900131 phony_.insert(input);
132 }
133 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900134 }
135
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900136 ~DepBuilder() {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900137 }
138
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900139 void Build(vector<Symbol> targets,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900140 vector<DepNode*>* nodes) {
Colin Cross5b26db32015-09-29 16:51:02 -0700141 if (!first_rule_) {
142 ERROR("*** No targets.");
143 }
144 CHECK(!first_rule_->outputs.empty());
Shinichiro Hamaji43defe02015-07-11 07:06:43 +0900145
Colin Cross5b26db32015-09-29 16:51:02 -0700146 first_rule_->is_default_target = true;
147
148 if (targets.empty()) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900149 targets.push_back(first_rule_->outputs[0]);
Shinichiro Hamaji319b6492015-09-24 14:23:55 +0900150 }
151 if (g_flags.gen_all_phony_targets) {
152 for (Symbol s : phony_)
153 targets.push_back(s);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900154 }
Shinichiro Hamaji7223e7b2015-09-28 15:17:27 +0900155 if (g_flags.gen_all_targets) {
156 for (const auto& p : rules_)
157 targets.push_back(p.first);
158 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900159
160 // TODO: LogStats?
161
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900162 for (Symbol target : targets) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900163 cur_rule_vars_.reset(new Vars);
164 ev_->set_current_scope(cur_rule_vars_.get());
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900165 DepNode* n = BuildPlan(target, Intern(""));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900166 nodes->push_back(n);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900167 ev_->set_current_scope(NULL);
168 cur_rule_vars_.reset(NULL);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900169 }
170 }
171
172 private:
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900173 bool Exists(Symbol target) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900174 auto found = rules_.find(target);
175 if (found != rules_.end())
176 return true;
177 if (phony_.count(target))
178 return true;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900179 return ::Exists(target.str());
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900180 }
181
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900182 void PopulateRules(const vector<shared_ptr<Rule>>& rules) {
183 for (shared_ptr<Rule> rule : rules) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900184 if (rule->outputs.empty()) {
185 PopulateImplicitRule(rule);
186 } else {
187 PopulateExplicitRule(rule);
188 }
189 }
Shinichiro Hamaji65657d92015-06-24 17:05:50 +0900190 for (auto& p : suffix_rules_) {
191 reverse(p.second.begin(), p.second.end());
192 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900193 }
194
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900195 bool PopulateSuffixRule(shared_ptr<Rule> rule, Symbol output) {
196 if (output.empty() || output.str()[0] != '.')
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900197 return false;
198
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900199 const StringPiece rest = StringPiece(output.str()).substr(1);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900200 size_t dot_index = rest.find('.');
201 // If there is only a single dot or the third dot, this is not a
202 // suffix rule.
203 if (dot_index == string::npos ||
204 rest.substr(dot_index+1).find('.') != string::npos) {
205 return false;
206 }
207
208 StringPiece input_suffix = rest.substr(0, dot_index);
209 StringPiece output_suffix = rest.substr(dot_index+1);
210 shared_ptr<Rule> r = make_shared<Rule>(*rule);
211 r->inputs.clear();
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900212 r->inputs.push_back(Intern(input_suffix));
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900213 r->is_suffix_rule = true;
214 suffix_rules_[output_suffix].push_back(r);
215 return true;
216 }
217
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900218 void ApplyOutputPattern(const Rule& r,
219 Symbol output,
220 const vector<Symbol>& inputs,
221 vector<Symbol>* out_inputs) {
222 if (inputs.empty())
223 return;
224 if (r.is_suffix_rule) {
225 for (Symbol input : inputs) {
226 out_inputs->push_back(ReplaceSuffix(output, input));
227 }
228 return;
229 }
230 if (r.output_patterns.empty()) {
231 copy(inputs.begin(), inputs.end(), back_inserter(*out_inputs));
232 return;
233 }
234 CHECK(r.output_patterns.size() == 1);
235 Pattern pat(r.output_patterns[0].str());
236 for (Symbol input : inputs) {
237 string buf;
238 pat.AppendSubst(output.str(), input.str(), &buf);
239 out_inputs->push_back(Intern(buf));
240 }
241 }
242
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900243 shared_ptr<Rule> MergeRules(const Rule& old_rule,
244 const Rule& rule,
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900245 Symbol output,
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900246 bool is_suffix_rule) {
247 if (old_rule.is_double_colon != rule.is_double_colon) {
248 ERROR("%s:%d: *** target file `%s' has both : and :: entries.",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900249 LOCF(rule.loc), output.str().c_str());
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900250 }
251 if (!old_rule.cmds.empty() && !rule.cmds.empty() &&
252 !is_suffix_rule && !rule.is_double_colon) {
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900253 WARN("%s:%d: warning: overriding commands for target `%s'",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900254 LOCF(rule.cmd_loc()), output.str().c_str());
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900255 WARN("%s:%d: warning: ignoring old commands for target `%s'",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900256 LOCF(old_rule.cmd_loc()), output.str().c_str());
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900257 }
258
259 shared_ptr<Rule> r = make_shared<Rule>(rule);
260 if (rule.is_double_colon) {
261 r->cmds.clear();
262 for (Value* c : old_rule.cmds)
263 r->cmds.push_back(c);
264 for (Value* c : rule.cmds)
265 r->cmds.push_back(c);
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900266 if (!rule.output_patterns.empty() && !old_rule.output_patterns.empty() &&
267 rule.output_patterns != old_rule.output_patterns) {
268 ERROR("%s:%d: TODO: merging two double rules with output patterns "
269 "is not supported", LOCF(rule.loc));
270 }
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900271 } else if (!old_rule.cmds.empty() && rule.cmds.empty()) {
272 r->cmds = old_rule.cmds;
273 }
Shinichiro Hamaji485f9122015-06-26 07:06:14 +0900274
Shinichiro Hamaji2e23e4a2015-06-26 07:33:16 +0900275 // If the latter rule has a command (regardless of the commands in
276 // |old_rule|), inputs in the latter rule has a priority.
Shinichiro Hamaji485f9122015-06-26 07:06:14 +0900277 if (rule.cmds.empty()) {
278 r->inputs = old_rule.inputs;
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900279 ApplyOutputPattern(rule, output, rule.inputs, &r->inputs);
Shinichiro Hamaji485f9122015-06-26 07:06:14 +0900280 r->order_only_inputs = old_rule.order_only_inputs;
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900281 ApplyOutputPattern(rule, output, rule.order_only_inputs,
282 &r->order_only_inputs);
283 r->output_patterns = old_rule.output_patterns;
Shinichiro Hamaji485f9122015-06-26 07:06:14 +0900284 } else {
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900285 ApplyOutputPattern(old_rule, output, old_rule.inputs, &r->inputs);
286 ApplyOutputPattern(old_rule, output, old_rule.order_only_inputs,
287 &r->order_only_inputs);
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900288 }
289 return r;
290 }
291
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900292 void PopulateExplicitRule(shared_ptr<Rule> orig_rule) {
293 for (Symbol output : orig_rule->outputs) {
294 const bool is_suffix_rule = PopulateSuffixRule(orig_rule, output);
Shinichiro Hamajie36dd562015-06-27 16:34:48 +0900295
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900296 shared_ptr<Rule> rule = make_shared<Rule>(*orig_rule);
Shinichiro Hamajie36dd562015-06-27 16:34:48 +0900297 rule->outputs.clear();
298 rule->outputs.push_back(output);
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900299
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900300 auto p = rules_.insert(make_pair(output, rule));
301 if (p.second) {
302 if (!first_rule_ && output.get(0) != '.') {
303 first_rule_ = rule;
304 }
305 } else {
Shinichiro Hamajie30b3be2015-06-19 16:15:42 +0900306 p.first->second =
307 MergeRules(*p.first->second, *rule, output, is_suffix_rule);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900308 }
309 }
310 }
311
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900312 void PopulateImplicitRule(shared_ptr<Rule> rule) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900313 for (Symbol output_pattern : rule->output_patterns) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900314 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900315 r->output_patterns.clear();
316 r->output_patterns.push_back(output_pattern);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900317 implicit_rules_->Add(output_pattern.str(), r);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900318 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900319 }
320
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900321 shared_ptr<Rule> LookupRule(Symbol o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900322 auto found = rules_.find(o);
323 if (found != rules_.end())
324 return found->second;
325 return NULL;
326 }
327
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900328 Vars* LookupRuleVars(Symbol o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900329 auto found = rule_vars_.find(o);
330 if (found != rule_vars_.end())
331 return found->second;
332 return NULL;
333 }
334
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900335 bool CanPickImplicitRule(shared_ptr<Rule> rule, Symbol output) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900336 CHECK(rule->output_patterns.size() == 1);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900337 Pattern pat(rule->output_patterns[0].str());
338 if (!pat.Match(output.str())) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900339 return false;
340 }
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900341 for (Symbol input : rule->inputs) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900342 string buf;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900343 pat.AppendSubst(output.str(), input.str(), &buf);
344 if (!Exists(Intern(buf)))
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900345 return false;
346 }
347 return true;
348 }
349
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900350 Vars* MergeImplicitRuleVars(Symbol output, Vars* vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900351 auto found = rule_vars_.find(output);
352 if (found == rule_vars_.end())
353 return vars;
354 if (vars == NULL)
355 return found->second;
356 // TODO: leak.
357 Vars* r = new Vars(*found->second);
358 for (auto p : *vars) {
359 (*r)[p.first] = p.second;
360 }
361 return r;
362 }
363
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900364 bool PickRule(Symbol output,
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900365 shared_ptr<Rule>* out_rule, Vars** out_var) {
366 shared_ptr<Rule> rule = LookupRule(output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900367 Vars* vars = LookupRuleVars(output);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900368 *out_rule = rule;
369 *out_var = vars;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900370 if (rule) {
371 if (!rule->cmds.empty()) {
372 return true;
373 }
374 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900375
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900376 vector<shared_ptr<Rule>> irules;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900377 implicit_rules_->Get(output.str(), &irules);
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900378 for (auto iter = irules.rbegin(); iter != irules.rend(); ++iter) {
379 shared_ptr<Rule> irule = *iter;
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900380 if (!CanPickImplicitRule(irule, output))
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900381 continue;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900382 if (rule) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900383 shared_ptr<Rule> r = make_shared<Rule>(*rule);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900384 r->output_patterns = irule->output_patterns;
Shinichiro Hamajid2c0fe12015-06-26 07:42:53 +0900385 r->inputs.clear();
386 r->inputs = irule->inputs;
387 copy(rule->inputs.begin(), rule->inputs.end(),
388 back_inserter(r->inputs));
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900389 r->cmds = irule->cmds;
390 r->loc = irule->loc;
391 r->cmd_lineno = irule->cmd_lineno;
392 *out_rule = r;
393 return true;
394 }
395 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900396 CHECK(irule->output_patterns.size() == 1);
397 vars = MergeImplicitRuleVars(irule->output_patterns[0], vars);
398 *out_var = vars;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900399 }
400 *out_rule = irule;
401 return true;
402 }
403
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900404 StringPiece output_suffix = GetExt(output.str());
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900405 if (output_suffix.get(0) != '.')
406 return rule.get();
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900407 output_suffix = output_suffix.substr(1);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900408
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900409 SuffixRuleMap::const_iterator found = suffix_rules_.find(output_suffix);
410 if (found == suffix_rules_.end())
411 return rule.get();
412
413 for (shared_ptr<Rule> irule : found->second) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900414 CHECK(irule->inputs.size() == 1);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900415 Symbol input = ReplaceSuffix(output, irule->inputs[0]);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900416 if (!Exists(input))
417 continue;
418
419 if (rule) {
420 shared_ptr<Rule> r = make_shared<Rule>(*rule);
421 r->inputs.insert(r->inputs.begin(), input);
422 r->cmds = irule->cmds;
423 r->loc = irule->loc;
424 r->cmd_lineno = irule->cmd_lineno;
425 *out_rule = r;
426 return true;
427 }
428 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900429 CHECK(irule->outputs.size() == 1);
430 vars = MergeImplicitRuleVars(irule->outputs[0], vars);
431 *out_var = vars;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900432 }
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900433 *out_rule = irule;
434 return true;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900435 }
436
437 return rule.get();
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900438 }
439
Shinichiro Hamaji8d503012015-07-03 16:26:15 +0900440 DepNode* BuildPlan(Symbol output, Symbol needed_by UNUSED) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900441 LOG("BuildPlan: %s for %s",
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900442 output.c_str(),
443 needed_by.c_str());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900444
445 auto found = done_.find(output);
446 if (found != done_.end()) {
447 return found->second;
448 }
449
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900450 DepNode* n = new DepNode(output, phony_.count(output));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900451 done_[output] = n;
452
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900453 shared_ptr<Rule> rule;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900454 Vars* vars;
455 if (!PickRule(output, &rule, &vars)) {
456 return n;
457 }
458
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +0900459 if (rule->output_patterns.size() >= 1) {
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900460 if (rule->output_patterns.size() != 1) {
461 fprintf(stderr, "hmm %s\n", rule->DebugString().c_str());
462 }
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +0900463 CHECK(rule->output_patterns.size() == 1);
464 n->output_pattern = rule->output_patterns[0];
465 }
466
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900467 vector<unique_ptr<ScopedVar>> sv;
468 if (vars) {
469 for (const auto& p : *vars) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900470 Symbol name = p.first;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900471 RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
472 CHECK(var);
473 Var* new_var = var->v();
474 if (var->op() == AssignOp::PLUS_EQ) {
475 Var* old_var = ev_->LookupVar(name);
476 if (old_var->IsDefined()) {
477 // TODO: This would be incorrect and has a leak.
478 shared_ptr<string> s = make_shared<string>();
479 old_var->Eval(ev_, s.get());
Shinichiro Hamaji3c785c72015-06-23 19:22:34 +0900480 if (!s->empty())
481 *s += ' ';
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900482 new_var->Eval(ev_, s.get());
Shinichiro Hamaji5081c712015-08-14 16:49:20 +0900483 new_var = new SimpleVar(*s, old_var->Origin());
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900484 }
485 } else if (var->op() == AssignOp::QUESTION_EQ) {
486 Var* old_var = ev_->LookupVar(name);
487 if (old_var->IsDefined()) {
488 continue;
489 }
490 }
Shinichiro Hamajie978a892015-08-17 16:53:40 +0900491 sv.emplace_back(new ScopedVar(cur_rule_vars_.get(), name, new_var));
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900492 }
493 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900494
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900495 ApplyOutputPattern(*rule, output, rule->inputs, &n->actual_inputs);
496 for (Symbol input : n->actual_inputs) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900497 DepNode* c = BuildPlan(input, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900498 n->deps.push_back(c);
499 }
500
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900501 vector<Symbol> order_only_inputs;
502 ApplyOutputPattern(*rule, output, rule->order_only_inputs,
503 &order_only_inputs);
504 for (Symbol input : order_only_inputs) {
Shinichiro Hamaji704e4fe2015-06-24 17:37:47 +0900505 DepNode* c = BuildPlan(input, output);
Shinichiro Hamaji183dbb92015-07-06 17:21:39 +0900506 n->order_onlys.push_back(c);
Shinichiro Hamaji704e4fe2015-06-24 17:37:47 +0900507 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900508
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900509 n->has_rule = true;
510 n->cmds = rule->cmds;
Colin Cross5b26db32015-09-29 16:51:02 -0700511 n->is_default_target = rule->is_default_target;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900512 if (cur_rule_vars_->empty()) {
513 n->rule_vars = NULL;
514 } else {
515 n->rule_vars = new Vars;
516 for (auto p : *cur_rule_vars_) {
517 n->rule_vars->insert(p);
518 }
519 }
520 n->loc = rule->loc;
521 if (!rule->cmds.empty() && rule->cmd_lineno)
522 n->loc.lineno = rule->cmd_lineno;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900523
524 return n;
525 }
526
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900527 Evaluator* ev_;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900528 unordered_map<Symbol, shared_ptr<Rule>> rules_;
529 const unordered_map<Symbol, Vars*>& rule_vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900530 unique_ptr<Vars> cur_rule_vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900531
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900532 unique_ptr<RuleTrie> implicit_rules_;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900533 typedef unordered_map<StringPiece, vector<shared_ptr<Rule>>> SuffixRuleMap;
534 SuffixRuleMap suffix_rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900535
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900536 shared_ptr<Rule> first_rule_;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900537 unordered_map<Symbol, DepNode*> done_;
538 unordered_set<Symbol> phony_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900539};
540
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900541void MakeDep(Evaluator* ev,
542 const vector<shared_ptr<Rule>>& rules,
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900543 const unordered_map<Symbol, Vars*>& rule_vars,
544 const vector<Symbol>& targets,
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900545 vector<DepNode*>* nodes) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900546 DepBuilder db(ev, rules, rule_vars);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900547 db.Build(targets, nodes);
548}
549
550void InitDepNodePool() {
551 g_dep_node_pool = new vector<DepNode*>;
552}
553
554void QuitDepNodePool() {
555 for (DepNode* n : *g_dep_node_pool)
556 delete n;
557 delete g_dep_node_pool;
558}