1 // 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
15 // +build ignore
16
17 #include "dep.h"
18
19 #include <algorithm>
20 #include <iterator>
21 #include <map>
22 #include <memory>
23 #include <unordered_map>
24 #include <unordered_set>
25
26 #include "eval.h"
27 #include "fileutil.h"
28 #include "flags.h"
29 #include "log.h"
30 #include "rule.h"
31 #include "stats.h"
32 #include "strutil.h"
33 #include "symtab.h"
34 #include "timeutil.h"
35 #include "var.h"
36
37 namespace {
38
39 static vector<DepNode*>* g_dep_node_pool;
40
ReplaceSuffix(Symbol s,Symbol newsuf)41 static Symbol ReplaceSuffix(Symbol s, Symbol newsuf) {
42 string r;
43 AppendString(StripExt(s.str()), &r);
44 r += '.';
45 AppendString(newsuf.str(), &r);
46 return Intern(r);
47 }
48
ApplyOutputPattern(const Rule & r,Symbol output,const vector<Symbol> & inputs,vector<Symbol> * out_inputs)49 void ApplyOutputPattern(const Rule& r,
50 Symbol output,
51 const vector<Symbol>& inputs,
52 vector<Symbol>* out_inputs) {
53 if (inputs.empty())
54 return;
55 if (r.is_suffix_rule) {
56 for (Symbol input : inputs) {
57 out_inputs->push_back(ReplaceSuffix(output, input));
58 }
59 return;
60 }
61 if (r.output_patterns.empty()) {
62 copy(inputs.begin(), inputs.end(), back_inserter(*out_inputs));
63 return;
64 }
65 CHECK(r.output_patterns.size() == 1);
66 Pattern pat(r.output_patterns[0].str());
67 for (Symbol input : inputs) {
68 string buf;
69 pat.AppendSubst(output.str(), input.str(), &buf);
70 out_inputs->push_back(Intern(buf));
71 }
72 }
73
74 class RuleTrie {
75 struct Entry {
Entry__anon45fbc8e20111::RuleTrie::Entry76 Entry(const Rule* r, StringPiece s)
77 : rule(r), suffix(s) {
78 }
79 const Rule* rule;
80 StringPiece suffix;
81 };
82
83 public:
RuleTrie()84 RuleTrie() {}
~RuleTrie()85 ~RuleTrie() {
86 for (auto& p : children_)
87 delete p.second;
88 }
89
Add(StringPiece name,const Rule * rule)90 void Add(StringPiece name, const Rule* rule) {
91 if (name.empty() || name[0] == '%') {
92 rules_.push_back(Entry(rule, name));
93 return;
94 }
95 const char c = name[0];
96 auto p = children_.emplace(c, nullptr);
97 if (p.second) {
98 p.first->second = new RuleTrie();
99 }
100 p.first->second->Add(name.substr(1), rule);
101 }
102
Get(StringPiece name,vector<const Rule * > * rules) const103 void Get(StringPiece name, vector<const Rule*>* rules) const {
104 for (const Entry& ent : rules_) {
105 if ((ent.suffix.empty() && name.empty()) ||
106 HasSuffix(name, ent.suffix.substr(1))) {
107 rules->push_back(ent.rule);
108 }
109 }
110 if (name.empty())
111 return;
112 auto found = children_.find(name[0]);
113 if (found != children_.end()) {
114 found->second->Get(name.substr(1), rules);
115 }
116 }
117
size() const118 size_t size() const {
119 size_t r = rules_.size();
120 for (const auto& c : children_)
121 r += c.second->size();
122 return r;
123 }
124
125 private:
126 vector<Entry> rules_;
127 unordered_map<char, RuleTrie*> children_;
128 };
129
130
IsSuffixRule(Symbol output)131 bool IsSuffixRule(Symbol output) {
132 if (output.empty() || output.str()[0] != '.')
133 return false;
134 const StringPiece rest = StringPiece(output.str()).substr(1);
135 size_t dot_index = rest.find('.');
136 // If there is only a single dot or the third dot, this is not a
137 // suffix rule.
138 if (dot_index == string::npos ||
139 rest.substr(dot_index+1).find('.') != string::npos) {
140 return false;
141 }
142 return true;
143 }
144
145 struct RuleMerger {
146 vector<const Rule*> rules;
147 const Rule* primary_rule;
148 bool is_double_colon;
149
RuleMerger__anon45fbc8e20111::RuleMerger150 RuleMerger()
151 : primary_rule(nullptr),
152 is_double_colon(false) {
153 }
154
AddRule__anon45fbc8e20111::RuleMerger155 void AddRule(Symbol output, const Rule* r) {
156 if (rules.empty()) {
157 is_double_colon = r->is_double_colon;
158 } else if (is_double_colon != r->is_double_colon) {
159 ERROR_LOC(r->loc, "*** target file `%s' has both : and :: entries.",
160 output.c_str());
161 }
162
163 if (primary_rule && !r->cmds.empty() &&
164 !IsSuffixRule(output) && !r->is_double_colon) {
165 WARN_LOC(r->cmd_loc(),
166 "warning: overriding commands for target `%s'",
167 output.c_str());
168 WARN_LOC(primary_rule->cmd_loc(),
169 "warning: ignoring old commands for target `%s'",
170 output.c_str());
171 primary_rule = r;
172 }
173 if (!primary_rule && !r->cmds.empty()) {
174 primary_rule = r;
175 }
176
177 rules.push_back(r);
178 }
179
FillDepNodeFromRule__anon45fbc8e20111::RuleMerger180 void FillDepNodeFromRule(Symbol output,
181 const Rule* r,
182 DepNode* n) const {
183 if (is_double_colon)
184 copy(r->cmds.begin(), r->cmds.end(), back_inserter(n->cmds));
185
186 ApplyOutputPattern(*r, output, r->inputs, &n->actual_inputs);
187 ApplyOutputPattern(*r, output, r->order_only_inputs,
188 &n->actual_order_only_inputs);
189
190 if (r->output_patterns.size() >= 1) {
191 CHECK(r->output_patterns.size() == 1);
192 n->output_pattern = r->output_patterns[0];
193 }
194 }
195
FillDepNodeLoc__anon45fbc8e20111::RuleMerger196 void FillDepNodeLoc(const Rule* r, DepNode* n) const {
197 n->loc = r->loc;
198 if (!r->cmds.empty() && r->cmd_lineno)
199 n->loc.lineno = r->cmd_lineno;
200 }
201
FillDepNode__anon45fbc8e20111::RuleMerger202 void FillDepNode(Symbol output,
203 const Rule* pattern_rule,
204 DepNode* n) const {
205 if (primary_rule) {
206 CHECK(!pattern_rule);
207 FillDepNodeFromRule(output, primary_rule, n);
208 FillDepNodeLoc(primary_rule, n);
209 n->cmds = primary_rule->cmds;
210 } else if (pattern_rule) {
211 FillDepNodeFromRule(output, pattern_rule, n);
212 FillDepNodeLoc(pattern_rule, n);
213 n->cmds = pattern_rule->cmds;
214 }
215
216 for (const Rule* r : rules) {
217 if (r == primary_rule)
218 continue;
219 FillDepNodeFromRule(output, r, n);
220 if (n->loc.filename == NULL)
221 n->loc = r->loc;
222 }
223 }
224 };
225
226 } // namespace
227
DepNode(Symbol o,bool p,bool r)228 DepNode::DepNode(Symbol o, bool p, bool r)
229 : output(o),
230 has_rule(false),
231 is_default_target(false),
232 is_phony(p),
233 is_restat(r),
234 rule_vars(NULL),
235 depfile_var(NULL),
236 ninja_pool_var(NULL),
237 output_pattern(Symbol::IsUninitialized()) {
238 g_dep_node_pool->push_back(this);
239 }
240
241 class DepBuilder {
242 public:
DepBuilder(Evaluator * ev,const vector<const Rule * > & rules,const unordered_map<Symbol,Vars * > & rule_vars)243 DepBuilder(Evaluator* ev,
244 const vector<const Rule*>& rules,
245 const unordered_map<Symbol, Vars*>& rule_vars)
246 : ev_(ev),
247 rule_vars_(rule_vars),
248 implicit_rules_(new RuleTrie()),
249 first_rule_(Symbol::IsUninitialized{}),
250 depfile_var_name_(Intern(".KATI_DEPFILE")),
251 ninja_pool_var_name_(Intern(".KATI_NINJA_POOL")) {
252 ScopedTimeReporter tr("make dep (populate)");
253 PopulateRules(rules);
254 // TODO?
255 //LOG_STAT("%zu variables", ev->mutable_vars()->size());
256 LOG_STAT("%zu explicit rules", rules_.size());
257 LOG_STAT("%zu implicit rules", implicit_rules_->size());
258 LOG_STAT("%zu suffix rules", suffix_rules_.size());
259
260 HandleSpecialTargets();
261 }
262
HandleSpecialTargets()263 void HandleSpecialTargets() {
264 Loc loc;
265 vector<Symbol> targets;
266
267 if (GetRuleInputs(Intern(".PHONY"), &targets, &loc)) {
268 for (Symbol t : targets)
269 phony_.insert(t);
270 }
271 if (GetRuleInputs(Intern(".KATI_RESTAT"), &targets, &loc)) {
272 for (Symbol t : targets)
273 restat_.insert(t);
274 }
275 if (GetRuleInputs(Intern(".SUFFIXES"), &targets, &loc)) {
276 if (targets.empty()) {
277 suffix_rules_.clear();
278 } else {
279 WARN_LOC(loc, "kati doesn't support .SUFFIXES with prerequisites");
280 }
281 }
282
283 // Note we can safely ignore .DELETE_ON_ERROR for --ninja mode.
284 static const char* kUnsupportedBuiltinTargets[] = {
285 ".DEFAULT",
286 ".PRECIOUS",
287 ".INTERMEDIATE",
288 ".SECONDARY",
289 ".SECONDEXPANSION",
290 ".IGNORE",
291 ".LOW_RESOLUTION_TIME",
292 ".SILENT",
293 ".EXPORT_ALL_VARIABLES",
294 ".NOTPARALLEL",
295 ".ONESHELL",
296 NULL
297 };
298 for (const char** p = kUnsupportedBuiltinTargets; *p; p++) {
299 if (GetRuleInputs(Intern(*p), &targets, &loc)) {
300 WARN_LOC(loc, "kati doesn't support %s", *p);
301 }
302 }
303 }
304
~DepBuilder()305 ~DepBuilder() {
306 }
307
Build(vector<Symbol> targets,vector<DepNode * > * nodes)308 void Build(vector<Symbol> targets, vector<DepNode*>* nodes) {
309 if (!first_rule_.IsValid()) {
310 ERROR("*** No targets.");
311 }
312
313 if (!g_flags.gen_all_targets && targets.empty()) {
314 targets.push_back(first_rule_);
315 }
316 if (g_flags.gen_all_targets) {
317 unordered_set<Symbol> non_root_targets;
318 for (const auto& p : rules_) {
319 for (const Rule* r : p.second.rules) {
320 for (Symbol t : r->inputs)
321 non_root_targets.insert(t);
322 for (Symbol t : r->order_only_inputs)
323 non_root_targets.insert(t);
324 }
325 }
326
327 for (const auto& p : rules_) {
328 Symbol t = p.first;
329 if (!non_root_targets.count(t)) {
330 targets.push_back(p.first);
331 }
332 }
333 }
334
335 // TODO: LogStats?
336
337 for (Symbol target : targets) {
338 cur_rule_vars_.reset(new Vars);
339 ev_->set_current_scope(cur_rule_vars_.get());
340 DepNode* n = BuildPlan(target, Intern(""));
341 nodes->push_back(n);
342 ev_->set_current_scope(NULL);
343 cur_rule_vars_.reset(NULL);
344 }
345 }
346
347 private:
Exists(Symbol target)348 bool Exists(Symbol target) {
349 auto found = rules_.find(target);
350 if (found != rules_.end())
351 return true;
352 if (phony_.count(target))
353 return true;
354 return ::Exists(target.str());
355 }
356
GetRuleInputs(Symbol s,vector<Symbol> * o,Loc * l)357 bool GetRuleInputs(Symbol s, vector<Symbol>* o, Loc* l) {
358 auto found = rules_.find(s);
359 if (found == rules_.end())
360 return false;
361
362 o->clear();
363 CHECK(!found->second.rules.empty());
364 *l = found->second.rules.front()->loc;
365 for (const Rule* r : found->second.rules) {
366 for (Symbol i : r->inputs)
367 o->push_back(i);
368 }
369 return true;
370 }
371
PopulateRules(const vector<const Rule * > & rules)372 void PopulateRules(const vector<const Rule*>& rules) {
373 for (const Rule* rule : rules) {
374 if (rule->outputs.empty()) {
375 PopulateImplicitRule(rule);
376 } else {
377 PopulateExplicitRule(rule);
378 }
379 }
380 for (auto& p : suffix_rules_) {
381 reverse(p.second.begin(), p.second.end());
382 }
383 }
384
PopulateSuffixRule(const Rule * rule,Symbol output)385 bool PopulateSuffixRule(const Rule* rule, Symbol output) {
386 if (!IsSuffixRule(output))
387 return false;
388
389 const StringPiece rest = StringPiece(output.str()).substr(1);
390 size_t dot_index = rest.find('.');
391
392 StringPiece input_suffix = rest.substr(0, dot_index);
393 StringPiece output_suffix = rest.substr(dot_index+1);
394 shared_ptr<Rule> r = make_shared<Rule>(*rule);
395 r->inputs.clear();
396 r->inputs.push_back(Intern(input_suffix));
397 r->is_suffix_rule = true;
398 suffix_rules_[output_suffix].push_back(r);
399 return true;
400 }
401
PopulateExplicitRule(const Rule * rule)402 void PopulateExplicitRule(const Rule* rule) {
403 for (Symbol output : rule->outputs) {
404 if (!first_rule_.IsValid() && output.get(0) != '.') {
405 first_rule_ = output;
406 }
407 rules_[output].AddRule(output, rule);
408 PopulateSuffixRule(rule, output);
409 }
410 }
411
IsIgnorableImplicitRule(const Rule * rule)412 static bool IsIgnorableImplicitRule(const Rule* rule) {
413 // As kati doesn't have RCS/SCCS related default rules, we can
414 // safely ignore suppression for them.
415 if (rule->inputs.size() != 1)
416 return false;
417 if (!rule->order_only_inputs.empty())
418 return false;
419 if (!rule->cmds.empty())
420 return false;
421 const string& i = rule->inputs[0].str();
422 return (i == "RCS/%,v" || i == "RCS/%" || i == "%,v" ||
423 i == "s.%" || i == "SCCS/s.%");
424 }
425
PopulateImplicitRule(const Rule * rule)426 void PopulateImplicitRule(const Rule* rule) {
427 for (Symbol output_pattern : rule->output_patterns) {
428 if (output_pattern.str() != "%" || !IsIgnorableImplicitRule(rule))
429 implicit_rules_->Add(output_pattern.str(), rule);
430 }
431 }
432
LookupRuleMerger(Symbol o)433 const RuleMerger* LookupRuleMerger(Symbol o) {
434 auto found = rules_.find(o);
435 if (found != rules_.end()) {
436 return &found->second;
437 }
438 return nullptr;
439 }
440
LookupRuleVars(Symbol o)441 Vars* LookupRuleVars(Symbol o) {
442 auto found = rule_vars_.find(o);
443 if (found != rule_vars_.end())
444 return found->second;
445 return nullptr;
446 }
447
CanPickImplicitRule(const Rule * rule,Symbol output,DepNode * n,shared_ptr<Rule> * out_rule)448 bool CanPickImplicitRule(const Rule* rule, Symbol output, DepNode* n,
449 shared_ptr<Rule>* out_rule) {
450 Symbol matched(Symbol::IsUninitialized{});
451 for (Symbol output_pattern : rule->output_patterns) {
452 Pattern pat(output_pattern.str());
453 if (pat.Match(output.str())) {
454 bool ok = true;
455 for (Symbol input : rule->inputs) {
456 string buf;
457 pat.AppendSubst(output.str(), input.str(), &buf);
458 if (!Exists(Intern(buf))) {
459 ok = false;
460 break;
461 }
462 }
463
464 if (ok) {
465 matched = output_pattern;
466 break;
467 }
468 }
469 }
470 if (!matched.IsValid())
471 return false;
472
473 *out_rule = make_shared<Rule>(*rule);
474 if ((*out_rule)->output_patterns.size() > 1) {
475 // We should mark all other output patterns as used.
476 Pattern pat(matched.str());
477 for (Symbol output_pattern : rule->output_patterns) {
478 if (output_pattern == matched)
479 continue;
480 string buf;
481 pat.AppendSubst(output.str(), output_pattern.str(), &buf);
482 done_[Intern(buf)] = n;
483 }
484 (*out_rule)->output_patterns.clear();
485 (*out_rule)->output_patterns.push_back(matched);
486 }
487
488 return true;
489 }
490
MergeImplicitRuleVars(Symbol output,Vars * vars)491 Vars* MergeImplicitRuleVars(Symbol output, Vars* vars) {
492 auto found = rule_vars_.find(output);
493 if (found == rule_vars_.end())
494 return vars;
495 if (vars == NULL)
496 return found->second;
497 // TODO: leak.
498 Vars* r = new Vars(*found->second);
499 for (auto p : *vars) {
500 (*r)[p.first] = p.second;
501 }
502 return r;
503 }
504
PickRule(Symbol output,DepNode * n,const RuleMerger ** out_rule_merger,shared_ptr<Rule> * pattern_rule,Vars ** out_var)505 bool PickRule(Symbol output,
506 DepNode* n,
507 const RuleMerger** out_rule_merger,
508 shared_ptr<Rule>* pattern_rule,
509 Vars** out_var) {
510 const RuleMerger* rule_merger = LookupRuleMerger(output);
511 Vars* vars = LookupRuleVars(output);
512 *out_rule_merger = rule_merger;
513 *out_var = vars;
514 if (rule_merger && rule_merger->primary_rule)
515 return true;
516
517 vector<const Rule*> irules;
518 implicit_rules_->Get(output.str(), &irules);
519 for (auto iter = irules.rbegin(); iter != irules.rend(); ++iter) {
520 if (!CanPickImplicitRule(*iter, output, n, pattern_rule))
521 continue;
522 if (rule_merger) {
523 return true;
524 }
525 CHECK((*pattern_rule)->output_patterns.size() == 1);
526 vars = MergeImplicitRuleVars((*pattern_rule)->output_patterns[0], vars);
527 *out_var = vars;
528 return true;
529 }
530
531 StringPiece output_suffix = GetExt(output.str());
532 if (output_suffix.get(0) != '.')
533 return rule_merger;
534 output_suffix = output_suffix.substr(1);
535
536 SuffixRuleMap::const_iterator found = suffix_rules_.find(output_suffix);
537 if (found == suffix_rules_.end())
538 return rule_merger;
539
540 for (const shared_ptr<Rule> &irule : found->second) {
541 CHECK(irule->inputs.size() == 1);
542 Symbol input = ReplaceSuffix(output, irule->inputs[0]);
543 if (!Exists(input))
544 continue;
545
546 *pattern_rule = irule;
547 if (rule_merger)
548 return true;
549 if (vars) {
550 CHECK(irule->outputs.size() == 1);
551 vars = MergeImplicitRuleVars(irule->outputs[0], vars);
552 *out_var = vars;
553 }
554 return true;
555 }
556
557 return rule_merger;
558 }
559
BuildPlan(Symbol output,Symbol needed_by UNUSED)560 DepNode* BuildPlan(Symbol output, Symbol needed_by UNUSED) {
561 LOG("BuildPlan: %s for %s",
562 output.c_str(),
563 needed_by.c_str());
564
565 auto found = done_.find(output);
566 if (found != done_.end()) {
567 return found->second;
568 }
569
570 DepNode* n = new DepNode(output,
571 phony_.count(output),
572 restat_.count(output));
573 done_[output] = n;
574
575 const RuleMerger* rule_merger = nullptr;
576 shared_ptr<Rule> pattern_rule;
577 Vars* vars;
578 if (!PickRule(output, n, &rule_merger, &pattern_rule, &vars)) {
579 return n;
580 }
581 if (rule_merger)
582 rule_merger->FillDepNode(output, pattern_rule.get(), n);
583 else
584 RuleMerger().FillDepNode(output, pattern_rule.get(), n);
585
586 vector<unique_ptr<ScopedVar>> sv;
587 if (vars) {
588 for (const auto& p : *vars) {
589 Symbol name = p.first;
590 RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
591 CHECK(var);
592 Var* new_var = var->v();
593 if (var->op() == AssignOp::PLUS_EQ) {
594 Var* old_var = ev_->LookupVar(name);
595 if (old_var->IsDefined()) {
596 // TODO: This would be incorrect and has a leak.
597 shared_ptr<string> s = make_shared<string>();
598 old_var->Eval(ev_, s.get());
599 if (!s->empty())
600 *s += ' ';
601 new_var->Eval(ev_, s.get());
602 new_var = new SimpleVar(*s, old_var->Origin());
603 }
604 } else if (var->op() == AssignOp::QUESTION_EQ) {
605 Var* old_var = ev_->LookupVar(name);
606 if (old_var->IsDefined()) {
607 continue;
608 }
609 }
610
611 if (name == depfile_var_name_) {
612 n->depfile_var = new_var;
613 } else if (name == ninja_pool_var_name_) {
614 n->ninja_pool_var = new_var;
615 } else {
616 sv.emplace_back(new ScopedVar(cur_rule_vars_.get(), name, new_var));
617 }
618 }
619 }
620
621 for (Symbol input : n->actual_inputs) {
622 DepNode* c = BuildPlan(input, output);
623 n->deps.push_back(c);
624 }
625
626 for (Symbol input : n->actual_order_only_inputs) {
627 DepNode* c = BuildPlan(input, output);
628 n->order_onlys.push_back(c);
629 }
630
631 n->has_rule = true;
632 n->is_default_target = first_rule_ == output;
633 if (cur_rule_vars_->empty()) {
634 n->rule_vars = NULL;
635 } else {
636 n->rule_vars = new Vars;
637 for (auto p : *cur_rule_vars_) {
638 n->rule_vars->insert(p);
639 }
640 }
641
642 return n;
643 }
644
645 Evaluator* ev_;
646 map<Symbol, RuleMerger> rules_;
647 const unordered_map<Symbol, Vars*>& rule_vars_;
648 unique_ptr<Vars> cur_rule_vars_;
649
650 unique_ptr<RuleTrie> implicit_rules_;
651 typedef unordered_map<StringPiece, vector<shared_ptr<Rule>>> SuffixRuleMap;
652 SuffixRuleMap suffix_rules_;
653
654 Symbol first_rule_;
655 unordered_map<Symbol, DepNode*> done_;
656 unordered_set<Symbol> phony_;
657 unordered_set<Symbol> restat_;
658 Symbol depfile_var_name_;
659 Symbol ninja_pool_var_name_;
660 };
661
MakeDep(Evaluator * ev,const vector<const Rule * > & rules,const unordered_map<Symbol,Vars * > & rule_vars,const vector<Symbol> & targets,vector<DepNode * > * nodes)662 void MakeDep(Evaluator* ev,
663 const vector<const Rule*>& rules,
664 const unordered_map<Symbol, Vars*>& rule_vars,
665 const vector<Symbol>& targets,
666 vector<DepNode*>* nodes) {
667 DepBuilder db(ev, rules, rule_vars);
668 ScopedTimeReporter tr("make dep (build)");
669 db.Build(targets, nodes);
670 }
671
InitDepNodePool()672 void InitDepNodePool() {
673 g_dep_node_pool = new vector<DepNode*>;
674 }
675
QuitDepNodePool()676 void QuitDepNodePool() {
677 for (DepNode* n : *g_dep_node_pool)
678 delete n;
679 delete g_dep_node_pool;
680 }
681