blob: d46541f68c013387ad33e913026c6dc1f5075c66 [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 "exec.h"
18
19#include <stdio.h>
20#include <stdlib.h>
21
22#include <memory>
23#include <unordered_map>
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090024#include <unordered_set>
25#include <utility>
26#include <vector>
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027
28#include "dep.h"
29#include "eval.h"
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +090030#include "fileutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090031#include "log.h"
32#include "string_piece.h"
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090033#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090034#include "value.h"
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090035#include "var.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090036
37namespace {
38
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090039class Executor;
40
41class AutoVar : public Var {
42 public:
43 virtual const char* Flavor() const override {
44 return "undefined";
45 }
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +090046 virtual VarOrigin Origin() const override {
47 return VarOrigin::AUTOMATIC;
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090048 }
49
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090050 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
51
Shinichiro Hamaji81699be2015-06-22 18:07:38 +090052 virtual StringPiece String() const override {
53 ERROR("$(value %s) is not implemented yet", sym_);
54 return "";
55 }
56
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090057 virtual string DebugString() const override {
58 return string("AutoVar(") + sym_ + ")";
59 }
60
61 protected:
62 AutoVar(Executor* ex, const char* sym) : ex_(ex), sym_(sym) {}
63 virtual ~AutoVar() = default;
64
65 Executor* ex_;
66 const char* sym_;
67};
68
69#define DECLARE_AUTO_VAR_CLASS(name) \
70 class name : public AutoVar { \
71 public: \
72 name(Executor* ex, const char* sym) \
73 : AutoVar(ex, sym) {} \
74 virtual ~name() = default; \
75 virtual void Eval(Evaluator* ev, string* s) const override; \
76 }
77
78DECLARE_AUTO_VAR_CLASS(AutoAtVar);
79DECLARE_AUTO_VAR_CLASS(AutoLessVar);
80DECLARE_AUTO_VAR_CLASS(AutoHatVar);
81DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
82DECLARE_AUTO_VAR_CLASS(AutoStarVar);
83
Shinichiro Hamaji22fede42015-06-18 18:38:32 +090084class AutoSuffixDVar : public AutoVar {
85 public:
86 AutoSuffixDVar(Executor* ex, const char* sym, Var* wrapped)
87 : AutoVar(ex, sym), wrapped_(wrapped) {
88 }
89 virtual ~AutoSuffixDVar() = default;
90 virtual void Eval(Evaluator* ev, string* s) const override;
91
92 private:
93 Var* wrapped_;
94};
95
96class AutoSuffixFVar : public AutoVar {
97 public:
98 AutoSuffixFVar(Executor* ex, const char* sym, Var* wrapped)
99 : AutoVar(ex, sym), wrapped_(wrapped) {}
100 virtual ~AutoSuffixFVar() = default;
101 virtual void Eval(Evaluator* ev, string* s) const override;
102
103 private:
104 Var* wrapped_;
105};
106
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900107struct Runner {
108 Runner()
109 : echo(true), ignore_error(false) {
110 }
111 StringPiece output;
112 shared_ptr<string> cmd;
113 bool echo;
114 bool ignore_error;
115 //StringPiece shell;
116};
117
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900118class Executor {
119 public:
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900120 explicit Executor(Evaluator* ev)
121 : ev_(ev) {
122 Vars* vars = ev_->mutable_vars();
Shinichiro Hamaji22fede42015-06-18 18:38:32 +0900123#define INSERT_AUTO_VAR(name, sym) do { \
124 Var* v = new name(this, sym); \
125 (*vars)[STRING_PIECE(sym)] = v; \
126 (*vars)[STRING_PIECE(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
127 (*vars)[STRING_PIECE(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900128 } while (0)
129 INSERT_AUTO_VAR(AutoAtVar, "@");
130 INSERT_AUTO_VAR(AutoLessVar, "<");
131 INSERT_AUTO_VAR(AutoHatVar, "^");
132 INSERT_AUTO_VAR(AutoPlusVar, "+");
133 INSERT_AUTO_VAR(AutoStarVar, "*");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900134 }
135
136 void ExecNode(DepNode* n, DepNode* needed_by) {
137 if (done_[n->output])
138 return;
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900139 done_[n->output] = true;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900140
141 LOG("ExecNode: %s for %s",
142 n->output.as_string().c_str(),
143 needed_by ? needed_by->output.as_string().c_str() : "(null)");
144
145 for (DepNode* d : n->deps) {
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900146 if (d->is_order_only && Exists(d->output)) {
147 continue;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900148 }
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900149 // TODO: Check the timestamp.
150 if (Exists(d->output)) {
151 continue;
152 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900153 ExecNode(d, n);
154 }
155
156 vector<Runner*> runners;
157 CreateRunners(n, &runners);
158 for (Runner* runner : runners) {
159 if (runner->echo) {
160 printf("%s\n", runner->cmd->c_str());
161 fflush(stdout);
162 }
Shinichiro Hamaji5e9def32015-06-24 22:27:48 +0900163 int result = system(runner->cmd->c_str());
164 if (result != 0) {
165 if (runner->ignore_error) {
166 fprintf(stderr, "[%.*s] Error %d (ignored)\n",
167 SPF(runner->output), WEXITSTATUS(result));
168 } else {
169 fprintf(stderr, "*** [%.*s] Error %d\n",
170 SPF(runner->output), WEXITSTATUS(result));
171 exit(1);
172 }
173 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900174 delete runner;
175 }
176 }
177
Shinichiro Hamaji1c448b12015-06-25 21:48:23 +0900178 void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
179 *s = TrimLeftSpace(*s);
180 while (true) {
181 char c = s->get(0);
182 if (c == '@') {
183 *echo = false;
184 } else if (c == '-') {
185 *ignore_error = true;
186 } else {
187 break;
188 }
189 *s = TrimLeftSpace(s->substr(1));
190 }
191 }
192
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900193 void CreateRunners(DepNode* n, vector<Runner*>* runners) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900194 ev_->set_current_scope(n->rule_vars);
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900195 current_dep_node_ = n;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900196 for (Value* v : n->cmds) {
Shinichiro Hamajia4d0ecb2015-06-24 22:08:30 +0900197 shared_ptr<string> cmds_buf = v->Eval(ev_);
Shinichiro Hamaji1c448b12015-06-25 21:48:23 +0900198 StringPiece cmds = *cmds_buf;
199 bool global_echo = true;
200 bool global_ignore_error = false;
201 ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error);
Shinichiro Hamaji70bbc4d2015-06-24 22:13:35 +0900202 if (cmds == "")
Shinichiro Hamaji0998b882015-06-24 16:59:18 +0900203 continue;
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900204 while (true) {
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900205 size_t lf_cnt;
206 size_t index = FindEndOfLine(cmds, 0, &lf_cnt);
207 if (index == cmds.size())
208 index = string::npos;
Shinichiro Hamajia4d0ecb2015-06-24 22:08:30 +0900209 StringPiece cmd = TrimLeftSpace(cmds.substr(0, index));
210 cmds = cmds.substr(index + 1);
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900211
Shinichiro Hamaji1c448b12015-06-25 21:48:23 +0900212 bool echo = global_echo;
213 bool ignore_error = global_ignore_error;
214 ParseCommandPrefixes(&cmd, &echo, &ignore_error);
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900215
Shinichiro Hamaji70bbc4d2015-06-24 22:13:35 +0900216 if (!cmd.empty()) {
217 Runner* runner = new Runner;
218 runner->output = n->output;
219 runner->cmd = make_shared<string>(cmd.as_string());
220 runner->echo = echo;
221 runner->ignore_error = ignore_error;
222 runners->push_back(runner);
223 }
224 if (index == string::npos)
225 break;
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900226 }
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900227 continue;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900228 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900229 ev_->set_current_scope(NULL);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900230 }
231
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900232 const DepNode* current_dep_node() const { return current_dep_node_; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900233
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900234 private:
235 Vars* vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900236 Evaluator* ev_;
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900237 unordered_map<StringPiece, bool> done_;
238 DepNode* current_dep_node_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900239};
240
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900241void AutoAtVar::Eval(Evaluator*, string* s) const {
242 AppendString(ex_->current_dep_node()->output, s);
243}
244
245void AutoLessVar::Eval(Evaluator*, string* s) const {
246 auto& ai = ex_->current_dep_node()->actual_inputs;
247 if (!ai.empty())
248 AppendString(ai[0], s);
249}
250
251void AutoHatVar::Eval(Evaluator*, string* s) const {
252 unordered_set<StringPiece> seen;
253 WordWriter ww(s);
254 for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
255 if (seen.insert(ai).second)
256 ww.Write(ai);
257 }
258}
259
260void AutoPlusVar::Eval(Evaluator*, string* s) const {
261 WordWriter ww(s);
262 for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
263 ww.Write(ai);
264 }
265}
266
267void AutoStarVar::Eval(Evaluator*, string* s) const {
268 AppendString(StripExt(ex_->current_dep_node()->output), s);
269}
270
Shinichiro Hamaji22fede42015-06-18 18:38:32 +0900271void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
272 string buf;
273 wrapped_->Eval(ev, &buf);
274 WordWriter ww(s);
275 for (StringPiece tok : WordScanner(buf)) {
276 ww.Write(Dirname(tok));
277 }
278}
279
280void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
281 string buf;
282 wrapped_->Eval(ev, &buf);
283 WordWriter ww(s);
284 for (StringPiece tok : WordScanner(buf)) {
285 ww.Write(Basename(tok));
286 }
287}
288
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900289} // namespace
290
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900291void Exec(const vector<DepNode*>& roots, Evaluator* ev) {
292 unique_ptr<Executor> executor(new Executor(ev));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900293 for (DepNode* root : roots) {
294 executor->ExecNode(root, NULL);
295 }
296}