blob: d72a62f834e738aa96572269b621950eb6b489a5 [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// 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
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "dep.h"
18
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090019#include <algorithm>
Shinichiro Hamaji485f9122015-06-26 07:06:14 +090020#include <iterator>
Dan Willemsenb248caa2015-10-01 16:07:48 -070021#include <map>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090022#include <memory>
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +090023#include <unordered_map>
24#include <unordered_set>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090025
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090026#include "eval.h"
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090027#include "fileutil.h"
Stefan Becker187bf082016-04-07 13:28:42 +030028#include "flags.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090029#include "log.h"
30#include "rule.h"
Shinichiro Hamaji54a3d532016-02-16 17:33:27 +090031#include "stats.h"
Shinichiro Hamaji4a711312015-06-19 14:44:20 +090032#include "strutil.h"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090033#include "symtab.h"
Shinichiro Hamaji54a3d532016-02-16 17:33:27 +090034#include "timeutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090035#include "var.h"
36
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090037namespace {
38
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090039static vector<DepNode*>* g_dep_node_pool;
40
Shinichiro Hamajie7992752015-06-29 18:38:35 +090041static Symbol ReplaceSuffix(Symbol s, Symbol newsuf) {
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090042 string r;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090043 AppendString(StripExt(s.str()), &r);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090044 r += '.';
Shinichiro Hamajie7992752015-06-29 18:38:35 +090045 AppendString(newsuf.str(), &r);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +090046 return Intern(r);
47}
48
Shinichiro Hamaji3727d212016-02-19 15:21:32 +090049void 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
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090074class RuleTrie {
75 struct Entry {
Dan Willemsen3ce083f2017-10-11 22:17:48 -070076 Entry(const Rule* r, StringPiece s) : rule(r), suffix(s) {}
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +090077 const Rule* rule;
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090078 StringPiece suffix;
79 };
80
81 public:
82 RuleTrie() {}
83 ~RuleTrie() {
84 for (auto& p : children_)
85 delete p.second;
86 }
87
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +090088 void Add(StringPiece name, const Rule* rule) {
Shinichiro Hamaji2a047892015-06-29 13:56:41 +090089 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
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +0900101 void Get(StringPiece name, vector<const Rule*>* rules) const {
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900102 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 }
Shinichiro Hamajif772b172015-06-29 16:05:44 +0900108 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 }
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900114 }
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
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900128bool 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 ||
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700136 rest.substr(dot_index + 1).find('.') != string::npos) {
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900137 return false;
138 }
139 return true;
140}
141
142struct RuleMerger {
143 vector<const Rule*> rules;
Dan Willemsen72a8e012017-08-13 22:06:47 -0700144 vector<pair<Symbol, RuleMerger*>> implicit_outputs;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900145 const Rule* primary_rule;
Dan Willemsen72a8e012017-08-13 22:06:47 -0700146 const RuleMerger* parent;
147 Symbol parent_sym;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900148 bool is_double_colon;
149
150 RuleMerger()
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800151 : primary_rule(nullptr), parent(nullptr), is_double_colon(false) {}
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900152
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700153 void AddImplicitOutput(Symbol output, RuleMerger* merger) {
Dan Willemsen72a8e012017-08-13 22:06:47 -0700154 implicit_outputs.push_back(make_pair(output, merger));
155 }
156
157 void SetImplicitOutput(Symbol output, Symbol p, const RuleMerger* merger) {
158 if (!merger->primary_rule) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700159 ERROR("*** implicit output `%s' on phony target `%s'", output.c_str(),
160 p.c_str());
Dan Willemsen72a8e012017-08-13 22:06:47 -0700161 }
162 if (parent) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700163 ERROR_LOC(merger->primary_rule->cmd_loc(),
164 "*** implicit output `%s' of `%s' was already defined by `%s' "
165 "at %s:%d",
166 output.c_str(), p.c_str(), parent_sym.c_str(),
Colin Cross9a73c882018-11-12 22:00:36 -0800167 LOCF(parent->primary_rule->cmd_loc()));
Dan Willemsen72a8e012017-08-13 22:06:47 -0700168 }
169 if (primary_rule) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700170 ERROR_LOC(primary_rule->cmd_loc(),
171 "*** implicit output `%s' may not have commands",
Dan Willemsen72a8e012017-08-13 22:06:47 -0700172 output.c_str());
173 }
174 parent = merger;
175 parent_sym = p;
176 }
177
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900178 void AddRule(Symbol output, const Rule* r) {
179 if (rules.empty()) {
180 is_double_colon = r->is_double_colon;
181 } else if (is_double_colon != r->is_double_colon) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800182 ERROR_LOC(r->loc, "*** target file `%s' has both : and :: entries.",
183 output.c_str());
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900184 }
185
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700186 if (primary_rule && !r->cmds.empty() && !IsSuffixRule(output) &&
187 !r->is_double_colon) {
Dan Willemsenf63a3fd2017-04-27 23:39:57 -0700188 if (g_flags.werror_overriding_commands) {
189 ERROR_LOC(r->cmd_loc(),
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700190 "*** overriding commands for target `%s', previously defined "
191 "at %s:%d",
Dan Willemsenf63a3fd2017-04-27 23:39:57 -0700192 output.c_str(), LOCF(primary_rule->cmd_loc()));
193 } else {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700194 WARN_LOC(r->cmd_loc(), "warning: overriding commands for target `%s'",
Dan Willemsenf63a3fd2017-04-27 23:39:57 -0700195 output.c_str());
196 WARN_LOC(primary_rule->cmd_loc(),
197 "warning: ignoring old commands for target `%s'",
198 output.c_str());
199 }
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900200 primary_rule = r;
201 }
202 if (!primary_rule && !r->cmds.empty()) {
203 primary_rule = r;
204 }
205
206 rules.push_back(r);
207 }
208
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700209 void FillDepNodeFromRule(Symbol output, const Rule* r, DepNode* n) const {
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900210 if (is_double_colon)
211 copy(r->cmds.begin(), r->cmds.end(), back_inserter(n->cmds));
212
213 ApplyOutputPattern(*r, output, r->inputs, &n->actual_inputs);
214 ApplyOutputPattern(*r, output, r->order_only_inputs,
215 &n->actual_order_only_inputs);
216
217 if (r->output_patterns.size() >= 1) {
218 CHECK(r->output_patterns.size() == 1);
219 n->output_pattern = r->output_patterns[0];
220 }
221 }
222
223 void FillDepNodeLoc(const Rule* r, DepNode* n) const {
224 n->loc = r->loc;
225 if (!r->cmds.empty() && r->cmd_lineno)
226 n->loc.lineno = r->cmd_lineno;
227 }
228
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700229 void FillDepNode(Symbol output, const Rule* pattern_rule, DepNode* n) const {
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900230 if (primary_rule) {
231 CHECK(!pattern_rule);
232 FillDepNodeFromRule(output, primary_rule, n);
233 FillDepNodeLoc(primary_rule, n);
234 n->cmds = primary_rule->cmds;
235 } else if (pattern_rule) {
236 FillDepNodeFromRule(output, pattern_rule, n);
237 FillDepNodeLoc(pattern_rule, n);
238 n->cmds = pattern_rule->cmds;
239 }
240
241 for (const Rule* r : rules) {
242 if (r == primary_rule)
243 continue;
244 FillDepNodeFromRule(output, r, n);
Shinichiro Hamajic58db9a2016-05-12 15:16:12 +0900245 if (n->loc.filename == NULL)
246 n->loc = r->loc;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900247 }
Dan Willemsen72a8e012017-08-13 22:06:47 -0700248
249 for (auto& implicit_output : implicit_outputs) {
250 n->implicit_outputs.push_back(implicit_output.first);
251 for (const Rule* r : implicit_output.second->rules) {
252 FillDepNodeFromRule(output, r, n);
253 }
254 }
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900255 }
256};
257
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900258} // namespace
259
Shinichiro Hamaji3ac2a092015-10-01 18:38:02 +0900260DepNode::DepNode(Symbol o, bool p, bool r)
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900261 : output(o),
262 has_rule(false),
Colin Cross5b26db32015-09-29 16:51:02 -0700263 is_default_target(false),
Shinichiro Hamaji3ac2a092015-10-01 18:38:02 +0900264 is_phony(p),
265 is_restat(r),
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +0900266 rule_vars(NULL),
Shinichiro Hamaji85e5ed02016-01-20 16:25:32 +0900267 depfile_var(NULL),
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700268 ninja_pool_var(NULL) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900269 g_dep_node_pool->push_back(this);
270}
271
272class DepBuilder {
273 public:
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900274 DepBuilder(Evaluator* ev,
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900275 const vector<const Rule*>& rules,
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900276 const unordered_map<Symbol, Vars*>& rule_vars)
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900277 : ev_(ev),
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900278 rule_vars_(rule_vars),
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900279 implicit_rules_(new RuleTrie()),
Dan Willemsen2f75ffa2016-11-04 16:57:57 -0700280 depfile_var_name_(Intern(".KATI_DEPFILE")),
Dan Willemsenb78d16f2017-08-09 16:51:34 -0700281 implicit_outputs_var_name_(Intern(".KATI_IMPLICIT_OUTPUTS")),
Dan Willemsen2f75ffa2016-11-04 16:57:57 -0700282 ninja_pool_var_name_(Intern(".KATI_NINJA_POOL")) {
Shinichiro Hamaji54a3d532016-02-16 17:33:27 +0900283 ScopedTimeReporter tr("make dep (populate)");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900284 PopulateRules(rules);
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900285 // TODO?
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700286 // LOG_STAT("%zu variables", ev->mutable_vars()->size());
Shinichiro Hamajib4969af2015-06-28 02:06:54 +0900287 LOG_STAT("%zu explicit rules", rules_.size());
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900288 LOG_STAT("%zu implicit rules", implicit_rules_->size());
Shinichiro Hamajib4969af2015-06-28 02:06:54 +0900289 LOG_STAT("%zu suffix rules", suffix_rules_.size());
Shinichiro Hamajid40b6fe2015-06-29 17:08:42 +0900290
Shinichiro Hamajia5ac4d92016-02-19 14:47:23 +0900291 HandleSpecialTargets();
292 }
293
294 void HandleSpecialTargets() {
295 Loc loc;
296 vector<Symbol> targets;
297
298 if (GetRuleInputs(Intern(".PHONY"), &targets, &loc)) {
299 for (Symbol t : targets)
300 phony_.insert(t);
Shinichiro Hamajid40b6fe2015-06-29 17:08:42 +0900301 }
Shinichiro Hamajia5ac4d92016-02-19 14:47:23 +0900302 if (GetRuleInputs(Intern(".KATI_RESTAT"), &targets, &loc)) {
303 for (Symbol t : targets)
304 restat_.insert(t);
Shinichiro Hamaji3ac2a092015-10-01 18:38:02 +0900305 }
Shinichiro Hamajia5ac4d92016-02-19 14:47:23 +0900306 if (GetRuleInputs(Intern(".SUFFIXES"), &targets, &loc)) {
307 if (targets.empty()) {
Shinichiro Hamajicbe9f492015-11-30 16:39:35 +0900308 suffix_rules_.clear();
309 } else {
Dan Willemsene41c7552017-02-22 14:31:16 -0800310 WARN_LOC(loc, "kati doesn't support .SUFFIXES with prerequisites");
Shinichiro Hamajicbe9f492015-11-30 16:39:35 +0900311 }
312 }
Shinichiro Hamaji77be80d2015-11-30 16:43:05 +0900313
314 // Note we can safely ignore .DELETE_ON_ERROR for --ninja mode.
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700315 static const char* kUnsupportedBuiltinTargets[] = {".DEFAULT",
316 ".PRECIOUS",
317 ".INTERMEDIATE",
318 ".SECONDARY",
319 ".SECONDEXPANSION",
320 ".IGNORE",
321 ".LOW_RESOLUTION_TIME",
322 ".SILENT",
323 ".EXPORT_ALL_VARIABLES",
324 ".NOTPARALLEL",
325 ".ONESHELL",
326 NULL};
Shinichiro Hamaji77be80d2015-11-30 16:43:05 +0900327 for (const char** p = kUnsupportedBuiltinTargets; *p; p++) {
Shinichiro Hamajia5ac4d92016-02-19 14:47:23 +0900328 if (GetRuleInputs(Intern(*p), &targets, &loc)) {
Dan Willemsene41c7552017-02-22 14:31:16 -0800329 WARN_LOC(loc, "kati doesn't support %s", *p);
Shinichiro Hamaji77be80d2015-11-30 16:43:05 +0900330 }
331 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900332 }
333
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700334 ~DepBuilder() {}
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900335
Sasha Smundake8f4d6d2018-07-27 10:34:04 -0700336 void Build(vector<Symbol> targets, vector<NamedDepNode>* nodes) {
Shinichiro Hamaji8f813fe2016-02-19 14:32:51 +0900337 if (!first_rule_.IsValid()) {
Colin Cross5b26db32015-09-29 16:51:02 -0700338 ERROR("*** No targets.");
339 }
Shinichiro Hamaji43defe02015-07-11 07:06:43 +0900340
Shinichiro Hamaji6ff74ce2015-10-03 11:58:35 +0900341 if (!g_flags.gen_all_targets && targets.empty()) {
Shinichiro Hamaji8f813fe2016-02-19 14:32:51 +0900342 targets.push_back(first_rule_);
Shinichiro Hamaji319b6492015-09-24 14:23:55 +0900343 }
Shinichiro Hamaji7223e7b2015-09-28 15:17:27 +0900344 if (g_flags.gen_all_targets) {
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700345 SymbolSet non_root_targets;
Shinichiro Hamaji6ff74ce2015-10-03 11:58:35 +0900346 for (const auto& p : rules_) {
Dan Willemsenec5ca2c2018-06-10 21:27:16 -0700347 if (p.first.get(0) == '.')
348 continue;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900349 for (const Rule* r : p.second.rules) {
350 for (Symbol t : r->inputs)
351 non_root_targets.insert(t);
352 for (Symbol t : r->order_only_inputs)
353 non_root_targets.insert(t);
354 }
Shinichiro Hamaji6ff74ce2015-10-03 11:58:35 +0900355 }
356
357 for (const auto& p : rules_) {
358 Symbol t = p.first;
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700359 if (!non_root_targets.exists(t) && t.get(0) != '.') {
Shinichiro Hamaji6ff74ce2015-10-03 11:58:35 +0900360 targets.push_back(p.first);
361 }
362 }
Shinichiro Hamaji7223e7b2015-09-28 15:17:27 +0900363 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900364
365 // TODO: LogStats?
366
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900367 for (Symbol target : targets) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900368 cur_rule_vars_.reset(new Vars);
369 ev_->set_current_scope(cur_rule_vars_.get());
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900370 DepNode* n = BuildPlan(target, Intern(""));
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800371 nodes->push_back({target, n});
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900372 ev_->set_current_scope(NULL);
373 cur_rule_vars_.reset(NULL);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900374 }
375 }
376
377 private:
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900378 bool Exists(Symbol target) {
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700379 return (rules_.find(target) != rules_.end()) || phony_.exists(target) ||
380 ::Exists(target.str());
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900381 }
382
Shinichiro Hamajia5ac4d92016-02-19 14:47:23 +0900383 bool GetRuleInputs(Symbol s, vector<Symbol>* o, Loc* l) {
384 auto found = rules_.find(s);
385 if (found == rules_.end())
386 return false;
387
388 o->clear();
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900389 CHECK(!found->second.rules.empty());
390 *l = found->second.rules.front()->loc;
391 for (const Rule* r : found->second.rules) {
392 for (Symbol i : r->inputs)
393 o->push_back(i);
Shinichiro Hamajia5ac4d92016-02-19 14:47:23 +0900394 }
395 return true;
396 }
397
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900398 void PopulateRules(const vector<const Rule*>& rules) {
399 for (const Rule* rule : rules) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900400 if (rule->outputs.empty()) {
401 PopulateImplicitRule(rule);
402 } else {
403 PopulateExplicitRule(rule);
404 }
405 }
Shinichiro Hamaji65657d92015-06-24 17:05:50 +0900406 for (auto& p : suffix_rules_) {
407 reverse(p.second.begin(), p.second.end());
408 }
Dan Willemsen72a8e012017-08-13 22:06:47 -0700409 for (auto& p : rules_) {
410 auto vars = LookupRuleVars(p.first);
411 if (!vars) {
412 continue;
413 }
414 auto var = vars->Lookup(implicit_outputs_var_name_);
415 if (!var->IsDefined()) {
416 continue;
417 }
418
419 string implicit_outputs;
420 var->Eval(ev_, &implicit_outputs);
421
422 for (StringPiece output : WordScanner(implicit_outputs)) {
423 Symbol sym = Intern(TrimLeadingCurdir(output));
424 rules_[sym].SetImplicitOutput(sym, p.first, &p.second);
425 p.second.AddImplicitOutput(sym, &rules_[sym]);
426 }
427 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900428 }
429
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900430 bool PopulateSuffixRule(const Rule* rule, Symbol output) {
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900431 if (!IsSuffixRule(output))
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900432 return false;
433
Dan Willemsen6aafee62018-06-10 12:48:47 -0700434 if (g_flags.werror_suffix_rules) {
435 ERROR_LOC(rule->loc, "*** suffix rules are obsolete: %s", output.c_str());
436 } else if (g_flags.warn_suffix_rules) {
437 WARN_LOC(rule->loc, "warning: suffix rules are deprecated: %s",
438 output.c_str());
439 }
440
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900441 const StringPiece rest = StringPiece(output.str()).substr(1);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900442 size_t dot_index = rest.find('.');
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900443
444 StringPiece input_suffix = rest.substr(0, dot_index);
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700445 StringPiece output_suffix = rest.substr(dot_index + 1);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900446 shared_ptr<Rule> r = make_shared<Rule>(*rule);
447 r->inputs.clear();
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900448 r->inputs.push_back(Intern(input_suffix));
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900449 r->is_suffix_rule = true;
450 suffix_rules_[output_suffix].push_back(r);
451 return true;
452 }
453
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900454 void PopulateExplicitRule(const Rule* rule) {
455 for (Symbol output : rule->outputs) {
456 if (!first_rule_.IsValid() && output.get(0) != '.') {
457 first_rule_ = output;
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900458 }
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900459 rules_[output].AddRule(output, rule);
460 PopulateSuffixRule(rule, output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900461 }
462 }
463
Shinichiro Hamaji0a6e2a42016-02-16 19:21:26 +0900464 static bool IsIgnorableImplicitRule(const Rule* rule) {
Shinichiro Hamaji6ba79642016-02-16 19:13:29 +0900465 // 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();
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700474 return (i == "RCS/%,v" || i == "RCS/%" || i == "%,v" || i == "s.%" ||
475 i == "SCCS/s.%");
Shinichiro Hamaji6ba79642016-02-16 19:13:29 +0900476 }
477
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900478 void PopulateImplicitRule(const Rule* rule) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900479 for (Symbol output_pattern : rule->output_patterns) {
Dan Willemsen6aafee62018-06-10 12:48:47 -0700480 if (output_pattern.str() != "%" || !IsIgnorableImplicitRule(rule)) {
481 if (g_flags.werror_implicit_rules) {
482 ERROR_LOC(rule->loc, "*** implicit rules are obsolete: %s",
483 output_pattern.c_str());
484 } else if (g_flags.warn_implicit_rules) {
485 WARN_LOC(rule->loc, "warning: implicit rules are deprecated: %s",
486 output_pattern.c_str());
487 }
488
Shinichiro Hamaji6ba79642016-02-16 19:13:29 +0900489 implicit_rules_->Add(output_pattern.str(), rule);
Dan Willemsen6aafee62018-06-10 12:48:47 -0700490 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900491 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900492 }
493
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900494 const RuleMerger* LookupRuleMerger(Symbol o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900495 auto found = rules_.find(o);
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900496 if (found != rules_.end()) {
497 return &found->second;
498 }
499 return nullptr;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900500 }
501
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900502 Vars* LookupRuleVars(Symbol o) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900503 auto found = rule_vars_.find(o);
504 if (found != rule_vars_.end())
505 return found->second;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900506 return nullptr;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900507 }
508
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700509 bool CanPickImplicitRule(const Rule* rule,
510 Symbol output,
511 DepNode* n,
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +0900512 shared_ptr<Rule>* out_rule) {
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700513 Symbol matched;
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +0900514 for (Symbol output_pattern : rule->output_patterns) {
515 Pattern pat(output_pattern.str());
516 if (pat.Match(output.str())) {
517 bool ok = true;
518 for (Symbol input : rule->inputs) {
519 string buf;
520 pat.AppendSubst(output.str(), input.str(), &buf);
521 if (!Exists(Intern(buf))) {
522 ok = false;
523 break;
524 }
525 }
526
527 if (ok) {
528 matched = output_pattern;
529 break;
530 }
531 }
532 }
533 if (!matched.IsValid())
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900534 return false;
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +0900535
536 *out_rule = make_shared<Rule>(*rule);
537 if ((*out_rule)->output_patterns.size() > 1) {
538 // We should mark all other output patterns as used.
539 Pattern pat(matched.str());
540 for (Symbol output_pattern : rule->output_patterns) {
541 if (output_pattern == matched)
542 continue;
543 string buf;
544 pat.AppendSubst(output.str(), output_pattern.str(), &buf);
545 done_[Intern(buf)] = n;
546 }
547 (*out_rule)->output_patterns.clear();
548 (*out_rule)->output_patterns.push_back(matched);
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900549 }
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +0900550
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900551 return true;
552 }
553
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900554 Vars* MergeImplicitRuleVars(Symbol output, Vars* vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900555 auto found = rule_vars_.find(output);
556 if (found == rule_vars_.end())
557 return vars;
558 if (vars == NULL)
559 return found->second;
560 // TODO: leak.
561 Vars* r = new Vars(*found->second);
562 for (auto p : *vars) {
563 (*r)[p.first] = p.second;
564 }
565 return r;
566 }
567
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900568 bool PickRule(Symbol output,
569 DepNode* n,
570 const RuleMerger** out_rule_merger,
571 shared_ptr<Rule>* pattern_rule,
572 Vars** out_var) {
573 const RuleMerger* rule_merger = LookupRuleMerger(output);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900574 Vars* vars = LookupRuleVars(output);
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900575 *out_rule_merger = rule_merger;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900576 *out_var = vars;
Dan Willemsen72a8e012017-08-13 22:06:47 -0700577 if (rule_merger && rule_merger->primary_rule) {
578 for (auto implicit_output : rule_merger->implicit_outputs) {
579 vars = MergeImplicitRuleVars(implicit_output.first, vars);
580 }
581 *out_var = vars;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900582 return true;
Dan Willemsen72a8e012017-08-13 22:06:47 -0700583 }
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900584
Shinichiro Hamaji7eac6652016-02-02 12:25:08 +0900585 vector<const Rule*> irules;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900586 implicit_rules_->Get(output.str(), &irules);
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900587 for (auto iter = irules.rbegin(); iter != irules.rend(); ++iter) {
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900588 if (!CanPickImplicitRule(*iter, output, n, pattern_rule))
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900589 continue;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900590 if (rule_merger) {
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900591 return true;
592 }
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900593 CHECK((*pattern_rule)->output_patterns.size() == 1);
594 vars = MergeImplicitRuleVars((*pattern_rule)->output_patterns[0], vars);
Shinichiro Hamaji271c5802016-01-26 15:11:57 +0900595 *out_var = vars;
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900596 return true;
597 }
598
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900599 StringPiece output_suffix = GetExt(output.str());
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900600 if (output_suffix.get(0) != '.')
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900601 return rule_merger;
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900602 output_suffix = output_suffix.substr(1);
Shinichiro Hamaji4a711312015-06-19 14:44:20 +0900603
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900604 SuffixRuleMap::const_iterator found = suffix_rules_.find(output_suffix);
605 if (found == suffix_rules_.end())
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900606 return rule_merger;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900607
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700608 for (const shared_ptr<Rule>& irule : found->second) {
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900609 CHECK(irule->inputs.size() == 1);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900610 Symbol input = ReplaceSuffix(output, irule->inputs[0]);
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900611 if (!Exists(input))
612 continue;
613
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900614 *pattern_rule = irule;
615 if (rule_merger)
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900616 return true;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900617 if (vars) {
Shinichiro Hamajidca79a32015-06-24 15:27:33 +0900618 CHECK(irule->outputs.size() == 1);
619 vars = MergeImplicitRuleVars(irule->outputs[0], vars);
620 *out_var = vars;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900621 }
Shinichiro Hamaji52dbb602015-06-19 15:57:07 +0900622 return true;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900623 }
624
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900625 return rule_merger;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900626 }
627
Shinichiro Hamaji8d503012015-07-03 16:26:15 +0900628 DepNode* BuildPlan(Symbol output, Symbol needed_by UNUSED) {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700629 LOG("BuildPlan: %s for %s", output.c_str(), needed_by.c_str());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900630
631 auto found = done_.find(output);
632 if (found != done_.end()) {
633 return found->second;
634 }
635
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700636 DepNode* n =
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700637 new DepNode(output, phony_.exists(output), restat_.exists(output));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900638 done_[output] = n;
639
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900640 const RuleMerger* rule_merger = nullptr;
641 shared_ptr<Rule> pattern_rule;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900642 Vars* vars;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900643 if (!PickRule(output, n, &rule_merger, &pattern_rule, &vars)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900644 return n;
645 }
Dan Willemsen72a8e012017-08-13 22:06:47 -0700646 if (rule_merger && rule_merger->parent) {
647 output = rule_merger->parent_sym;
648 done_[output] = n;
649 n->output = output;
650 if (!PickRule(output, n, &rule_merger, &pattern_rule, &vars)) {
651 return n;
652 }
653 }
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900654 if (rule_merger)
655 rule_merger->FillDepNode(output, pattern_rule.get(), n);
656 else
657 RuleMerger().FillDepNode(output, pattern_rule.get(), n);
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +0900658
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900659 vector<unique_ptr<ScopedVar>> sv;
660 if (vars) {
661 for (const auto& p : *vars) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900662 Symbol name = p.first;
Sasha Smundakae1d58c2018-08-22 09:39:42 -0700663 Var* var = p.second;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900664 CHECK(var);
Sasha Smundakae1d58c2018-08-22 09:39:42 -0700665 Var* new_var = var;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900666 if (var->op() == AssignOp::PLUS_EQ) {
667 Var* old_var = ev_->LookupVar(name);
668 if (old_var->IsDefined()) {
669 // TODO: This would be incorrect and has a leak.
670 shared_ptr<string> s = make_shared<string>();
671 old_var->Eval(ev_, s.get());
Shinichiro Hamaji3c785c72015-06-23 19:22:34 +0900672 if (!s->empty())
673 *s += ' ';
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900674 new_var->Eval(ev_, s.get());
Shinichiro Hamaji5081c712015-08-14 16:49:20 +0900675 new_var = new SimpleVar(*s, old_var->Origin());
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900676 }
677 } else if (var->op() == AssignOp::QUESTION_EQ) {
678 Var* old_var = ev_->LookupVar(name);
679 if (old_var->IsDefined()) {
680 continue;
681 }
682 }
Shinichiro Hamaji85e5ed02016-01-20 16:25:32 +0900683
684 if (name == depfile_var_name_) {
685 n->depfile_var = new_var;
Dan Willemsenb78d16f2017-08-09 16:51:34 -0700686 } else if (name == implicit_outputs_var_name_) {
Dan Willemsen2f75ffa2016-11-04 16:57:57 -0700687 } else if (name == ninja_pool_var_name_) {
688 n->ninja_pool_var = new_var;
Shinichiro Hamaji85e5ed02016-01-20 16:25:32 +0900689 } else {
690 sv.emplace_back(new ScopedVar(cur_rule_vars_.get(), name, new_var));
691 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900692 }
693 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900694
Dan Willemsen8b551c52018-06-08 16:39:23 -0700695 if (g_flags.warn_phony_looks_real && n->is_phony &&
696 output.str().find("/") != string::npos) {
697 if (g_flags.werror_phony_looks_real) {
698 ERROR_LOC(
699 n->loc,
700 "*** PHONY target \"%s\" looks like a real file (contains a \"/\")",
701 output.c_str());
702 } else {
703 WARN_LOC(n->loc,
704 "warning: PHONY target \"%s\" looks like a real file "
705 "(contains a \"/\")",
706 output.c_str());
707 }
708 }
709
Dan Willemsena42898a2018-06-09 12:09:27 -0700710 if (!g_flags.writable.empty() && !n->is_phony) {
711 bool found = false;
712 for (const auto& w : g_flags.writable) {
713 if (StringPiece(output.str()).starts_with(w)) {
714 found = true;
715 break;
716 }
717 }
718 if (!found) {
719 if (g_flags.werror_writable) {
720 ERROR_LOC(n->loc, "*** writing to readonly directory: \"%s\"",
721 output.c_str());
722 } else {
723 WARN_LOC(n->loc, "warning: writing to readonly directory: \"%s\"",
724 output.c_str());
725 }
726 }
727 }
728
Dan Willemsen72a8e012017-08-13 22:06:47 -0700729 for (Symbol output : n->implicit_outputs) {
730 done_[output] = n;
Dan Willemsen8b551c52018-06-08 16:39:23 -0700731
732 if (g_flags.warn_phony_looks_real && n->is_phony &&
733 output.str().find("/") != string::npos) {
734 if (g_flags.werror_phony_looks_real) {
735 ERROR_LOC(n->loc,
736 "*** PHONY target \"%s\" looks like a real file (contains "
737 "a \"/\")",
738 output.c_str());
739 } else {
740 WARN_LOC(n->loc,
741 "warning: PHONY target \"%s\" looks like a real file "
742 "(contains a \"/\")",
743 output.c_str());
744 }
745 }
Dan Willemsena42898a2018-06-09 12:09:27 -0700746
747 if (!g_flags.writable.empty() && !n->is_phony) {
748 bool found = false;
749 for (const auto& w : g_flags.writable) {
750 if (StringPiece(output.str()).starts_with(w)) {
751 found = true;
752 break;
753 }
754 }
755 if (!found) {
756 if (g_flags.werror_writable) {
757 ERROR_LOC(n->loc, "*** writing to readonly directory: \"%s\"",
758 output.c_str());
759 } else {
760 WARN_LOC(n->loc, "warning: writing to readonly directory: \"%s\"",
761 output.c_str());
762 }
763 }
764 }
Dan Willemsen72a8e012017-08-13 22:06:47 -0700765 }
766
Shinichiro Hamaji53ffb072015-09-26 12:07:22 +0900767 for (Symbol input : n->actual_inputs) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900768 DepNode* c = BuildPlan(input, output);
Sasha Smundake8f4d6d2018-07-27 10:34:04 -0700769 n->deps.push_back({input, c});
Dan Willemsen8b551c52018-06-08 16:39:23 -0700770
Dan Willemsen40f26e12019-01-21 12:32:18 -0800771 bool is_phony = c->is_phony;
772 if (!is_phony && !c->has_rule && g_flags.top_level_phony) {
773 is_phony = input.str().find("/") == string::npos;
774 }
775 if (!n->is_phony && is_phony) {
Dan Willemsen8b551c52018-06-08 16:39:23 -0700776 if (g_flags.werror_real_to_phony) {
777 ERROR_LOC(n->loc,
778 "*** real file \"%s\" depends on PHONY target \"%s\"",
779 output.c_str(), input.c_str());
780 } else if (g_flags.warn_real_to_phony) {
781 WARN_LOC(n->loc,
782 "warning: real file \"%s\" depends on PHONY target \"%s\"",
783 output.c_str(), input.c_str());
784 }
785 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900786 }
787
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900788 for (Symbol input : n->actual_order_only_inputs) {
Shinichiro Hamaji704e4fe2015-06-24 17:37:47 +0900789 DepNode* c = BuildPlan(input, output);
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800790 n->order_onlys.push_back({input, c});
Shinichiro Hamaji704e4fe2015-06-24 17:37:47 +0900791 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900792
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900793 n->has_rule = true;
Shinichiro Hamaji0325b162016-02-19 14:55:09 +0900794 n->is_default_target = first_rule_ == output;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900795 if (cur_rule_vars_->empty()) {
796 n->rule_vars = NULL;
797 } else {
798 n->rule_vars = new Vars;
799 for (auto p : *cur_rule_vars_) {
800 n->rule_vars->insert(p);
801 }
802 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900803
804 return n;
805 }
806
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900807 Evaluator* ev_;
Shinichiro Hamaji3727d212016-02-19 15:21:32 +0900808 map<Symbol, RuleMerger> rules_;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900809 const unordered_map<Symbol, Vars*>& rule_vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900810 unique_ptr<Vars> cur_rule_vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900811
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900812 unique_ptr<RuleTrie> implicit_rules_;
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900813 typedef unordered_map<StringPiece, vector<shared_ptr<Rule>>> SuffixRuleMap;
814 SuffixRuleMap suffix_rules_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900815
Shinichiro Hamaji8f813fe2016-02-19 14:32:51 +0900816 Symbol first_rule_;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900817 unordered_map<Symbol, DepNode*> done_;
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700818 SymbolSet phony_;
819 SymbolSet restat_;
Shinichiro Hamaji85e5ed02016-01-20 16:25:32 +0900820 Symbol depfile_var_name_;
Dan Willemsenb78d16f2017-08-09 16:51:34 -0700821 Symbol implicit_outputs_var_name_;
Dan Willemsen2f75ffa2016-11-04 16:57:57 -0700822 Symbol ninja_pool_var_name_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900823};
824
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900825void MakeDep(Evaluator* ev,
Shinichiro Hamaji7a2659e2016-02-08 14:32:56 +0900826 const vector<const Rule*>& rules,
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900827 const unordered_map<Symbol, Vars*>& rule_vars,
828 const vector<Symbol>& targets,
Sasha Smundake8f4d6d2018-07-27 10:34:04 -0700829 vector<NamedDepNode>* nodes) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900830 DepBuilder db(ev, rules, rule_vars);
Shinichiro Hamaji54a3d532016-02-16 17:33:27 +0900831 ScopedTimeReporter tr("make dep (build)");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900832 db.Build(targets, nodes);
833}
834
835void InitDepNodePool() {
836 g_dep_node_pool = new vector<DepNode*>;
837}
838
839void QuitDepNodePool() {
840 for (DepNode* n : *g_dep_node_pool)
841 delete n;
842 delete g_dep_node_pool;
843}