blob: 665ac17b7360ec355202f0dfb168a71646f447c1 [file] [log] [blame]
Shinichiro Hamaji776ca302015-06-06 03:52:48 +09001#include "exec.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5
6#include <memory>
7#include <unordered_map>
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +09008#include <unordered_set>
9#include <utility>
10#include <vector>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090011
12#include "dep.h"
13#include "eval.h"
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +090014#include "fileutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090015#include "log.h"
16#include "string_piece.h"
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090017#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090018#include "value.h"
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090019#include "var.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090020
21namespace {
22
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090023class Executor;
24
25class AutoVar : public Var {
26 public:
27 virtual const char* Flavor() const override {
28 return "undefined";
29 }
30 virtual const char* Origin() const override {
31 return "automatic";
32 }
33
34 virtual bool IsDefined() const override { CHECK(false); }
35 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
36
Shinichiro Hamaji81699be2015-06-22 18:07:38 +090037 virtual StringPiece String() const override {
38 ERROR("$(value %s) is not implemented yet", sym_);
39 return "";
40 }
41
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090042 virtual string DebugString() const override {
43 return string("AutoVar(") + sym_ + ")";
44 }
45
46 protected:
47 AutoVar(Executor* ex, const char* sym) : ex_(ex), sym_(sym) {}
48 virtual ~AutoVar() = default;
49
50 Executor* ex_;
51 const char* sym_;
52};
53
54#define DECLARE_AUTO_VAR_CLASS(name) \
55 class name : public AutoVar { \
56 public: \
57 name(Executor* ex, const char* sym) \
58 : AutoVar(ex, sym) {} \
59 virtual ~name() = default; \
60 virtual void Eval(Evaluator* ev, string* s) const override; \
61 }
62
63DECLARE_AUTO_VAR_CLASS(AutoAtVar);
64DECLARE_AUTO_VAR_CLASS(AutoLessVar);
65DECLARE_AUTO_VAR_CLASS(AutoHatVar);
66DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
67DECLARE_AUTO_VAR_CLASS(AutoStarVar);
68
Shinichiro Hamaji22fede42015-06-18 18:38:32 +090069class AutoSuffixDVar : public AutoVar {
70 public:
71 AutoSuffixDVar(Executor* ex, const char* sym, Var* wrapped)
72 : AutoVar(ex, sym), wrapped_(wrapped) {
73 }
74 virtual ~AutoSuffixDVar() = default;
75 virtual void Eval(Evaluator* ev, string* s) const override;
76
77 private:
78 Var* wrapped_;
79};
80
81class AutoSuffixFVar : public AutoVar {
82 public:
83 AutoSuffixFVar(Executor* ex, const char* sym, Var* wrapped)
84 : AutoVar(ex, sym), wrapped_(wrapped) {}
85 virtual ~AutoSuffixFVar() = default;
86 virtual void Eval(Evaluator* ev, string* s) const override;
87
88 private:
89 Var* wrapped_;
90};
91
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090092struct Runner {
93 Runner()
94 : echo(true), ignore_error(false) {
95 }
96 StringPiece output;
97 shared_ptr<string> cmd;
98 bool echo;
99 bool ignore_error;
100 //StringPiece shell;
101};
102
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900103class Executor {
104 public:
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900105 explicit Executor(Vars* vars)
106 : vars_(vars),
107 ev_(new Evaluator(vars_)) {
Shinichiro Hamaji22fede42015-06-18 18:38:32 +0900108#define INSERT_AUTO_VAR(name, sym) do { \
109 Var* v = new name(this, sym); \
110 (*vars)[STRING_PIECE(sym)] = v; \
111 (*vars)[STRING_PIECE(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
112 (*vars)[STRING_PIECE(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900113 } while (0)
114 INSERT_AUTO_VAR(AutoAtVar, "@");
115 INSERT_AUTO_VAR(AutoLessVar, "<");
116 INSERT_AUTO_VAR(AutoHatVar, "^");
117 INSERT_AUTO_VAR(AutoPlusVar, "+");
118 INSERT_AUTO_VAR(AutoStarVar, "*");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900119 }
120
121 void ExecNode(DepNode* n, DepNode* needed_by) {
122 if (done_[n->output])
123 return;
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900124 done_[n->output] = true;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900125
126 LOG("ExecNode: %s for %s",
127 n->output.as_string().c_str(),
128 needed_by ? needed_by->output.as_string().c_str() : "(null)");
129
130 for (DepNode* d : n->deps) {
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900131 if (d->is_order_only && Exists(d->output)) {
132 continue;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900133 }
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900134 // TODO: Check the timestamp.
135 if (Exists(d->output)) {
136 continue;
137 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900138 ExecNode(d, n);
139 }
140
141 vector<Runner*> runners;
142 CreateRunners(n, &runners);
143 for (Runner* runner : runners) {
144 if (runner->echo) {
145 printf("%s\n", runner->cmd->c_str());
146 fflush(stdout);
147 }
148 system(runner->cmd->c_str());
149 delete runner;
150 }
151 }
152
153 void CreateRunners(DepNode* n, vector<Runner*>* runners) {
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900154 current_dep_node_ = n;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900155 for (Value* v : n->cmds) {
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900156 shared_ptr<string> cmd = v->Eval(ev_.get());
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900157 while (true) {
158 size_t index = cmd->find('\n');
159 if (index == string::npos)
160 break;
161
162 Runner* runner = new Runner;
163 runner->output = n->output;
164 runner->cmd = make_shared<string>(cmd->substr(0, index));
165 runners->push_back(runner);
166 cmd = make_shared<string>(cmd->substr(index + 1));
167 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900168 Runner* runner = new Runner;
169 runner->output = n->output;
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900170 runner->cmd = cmd;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900171 runners->push_back(runner);
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900172 continue;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900173 }
174 }
175
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900176 const DepNode* current_dep_node() const { return current_dep_node_; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900177
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900178 private:
179 Vars* vars_;
180 unique_ptr<Evaluator> ev_;
181 unordered_map<StringPiece, bool> done_;
182 DepNode* current_dep_node_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900183};
184
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900185void AutoAtVar::Eval(Evaluator*, string* s) const {
186 AppendString(ex_->current_dep_node()->output, s);
187}
188
189void AutoLessVar::Eval(Evaluator*, string* s) const {
190 auto& ai = ex_->current_dep_node()->actual_inputs;
191 if (!ai.empty())
192 AppendString(ai[0], s);
193}
194
195void AutoHatVar::Eval(Evaluator*, string* s) const {
196 unordered_set<StringPiece> seen;
197 WordWriter ww(s);
198 for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
199 if (seen.insert(ai).second)
200 ww.Write(ai);
201 }
202}
203
204void AutoPlusVar::Eval(Evaluator*, string* s) const {
205 WordWriter ww(s);
206 for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
207 ww.Write(ai);
208 }
209}
210
211void AutoStarVar::Eval(Evaluator*, string* s) const {
212 AppendString(StripExt(ex_->current_dep_node()->output), s);
213}
214
Shinichiro Hamaji22fede42015-06-18 18:38:32 +0900215void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
216 string buf;
217 wrapped_->Eval(ev, &buf);
218 WordWriter ww(s);
219 for (StringPiece tok : WordScanner(buf)) {
220 ww.Write(Dirname(tok));
221 }
222}
223
224void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
225 string buf;
226 wrapped_->Eval(ev, &buf);
227 WordWriter ww(s);
228 for (StringPiece tok : WordScanner(buf)) {
229 ww.Write(Basename(tok));
230 }
231}
232
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900233} // namespace
234
235void Exec(const vector<DepNode*>& roots, Vars* vars) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900236 unique_ptr<Executor> executor(new Executor(vars));
237 for (DepNode* root : roots) {
238 executor->ExecNode(root, NULL);
239 }
240}