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 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 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 { 75 Entry(const Rule* r, StringPiece s) 76 : rule(r), suffix(s) { 77 } 78 const Rule* rule; 79 StringPiece suffix; 80 }; 81 82 public: 83 RuleTrie() {} 84 ~RuleTrie() { 85 for (auto& p : children_) 86 delete p.second; 87 } 88 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 102 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 117 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 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 149 RuleMerger() 150 : primary_rule(nullptr), 151 is_double_colon(false) { 152 } 153 154 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 177 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 193 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 199 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 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: 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 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 300 ~DepBuilder() { 301 } 302 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: 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 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 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 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 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 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 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 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 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 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 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 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 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 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 664 void InitDepNodePool() { 665 g_dep_node_pool = new vector<DepNode*>; 666 } 667 668 void QuitDepNodePool() { 669 for (DepNode* n : *g_dep_node_pool) 670 delete n; 671 delete g_dep_node_pool; 672 } 673