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