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