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