blob: bc4497f86a6349ea3cc24ab367ec7e68c2282a66 [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 Hamaji08808d32015-06-26 08:02:45 +090031#include "flags.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090032#include "log.h"
33#include "string_piece.h"
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090034#include "strutil.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090035#include "value.h"
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090036#include "var.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090037
38namespace {
39
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090040class Executor;
41
42class AutoVar : public Var {
43 public:
44 virtual const char* Flavor() const override {
45 return "undefined";
46 }
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +090047 virtual VarOrigin Origin() const override {
48 return VarOrigin::AUTOMATIC;
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090049 }
50
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090051 virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
52
Shinichiro Hamaji81699be2015-06-22 18:07:38 +090053 virtual StringPiece String() const override {
54 ERROR("$(value %s) is not implemented yet", sym_);
55 return "";
56 }
57
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +090058 virtual string DebugString() const override {
59 return string("AutoVar(") + sym_ + ")";
60 }
61
62 protected:
63 AutoVar(Executor* ex, const char* sym) : ex_(ex), sym_(sym) {}
64 virtual ~AutoVar() = default;
65
66 Executor* ex_;
67 const char* sym_;
68};
69
70#define DECLARE_AUTO_VAR_CLASS(name) \
71 class name : public AutoVar { \
72 public: \
73 name(Executor* ex, const char* sym) \
74 : AutoVar(ex, sym) {} \
75 virtual ~name() = default; \
76 virtual void Eval(Evaluator* ev, string* s) const override; \
77 }
78
79DECLARE_AUTO_VAR_CLASS(AutoAtVar);
80DECLARE_AUTO_VAR_CLASS(AutoLessVar);
81DECLARE_AUTO_VAR_CLASS(AutoHatVar);
82DECLARE_AUTO_VAR_CLASS(AutoPlusVar);
83DECLARE_AUTO_VAR_CLASS(AutoStarVar);
84
Shinichiro Hamaji22fede42015-06-18 18:38:32 +090085class AutoSuffixDVar : public AutoVar {
86 public:
87 AutoSuffixDVar(Executor* ex, const char* sym, Var* wrapped)
88 : AutoVar(ex, sym), wrapped_(wrapped) {
89 }
90 virtual ~AutoSuffixDVar() = default;
91 virtual void Eval(Evaluator* ev, string* s) const override;
92
93 private:
94 Var* wrapped_;
95};
96
97class AutoSuffixFVar : public AutoVar {
98 public:
99 AutoSuffixFVar(Executor* ex, const char* sym, Var* wrapped)
100 : AutoVar(ex, sym), wrapped_(wrapped) {}
101 virtual ~AutoSuffixFVar() = default;
102 virtual void Eval(Evaluator* ev, string* s) const override;
103
104 private:
105 Var* wrapped_;
106};
107
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900108struct Runner {
109 Runner()
110 : echo(true), ignore_error(false) {
111 }
112 StringPiece output;
113 shared_ptr<string> cmd;
114 bool echo;
115 bool ignore_error;
116 //StringPiece shell;
117};
118
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900119class Executor {
120 public:
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900121 explicit Executor(Evaluator* ev)
122 : ev_(ev) {
123 Vars* vars = ev_->mutable_vars();
Shinichiro Hamaji22fede42015-06-18 18:38:32 +0900124#define INSERT_AUTO_VAR(name, sym) do { \
125 Var* v = new name(this, sym); \
126 (*vars)[STRING_PIECE(sym)] = v; \
127 (*vars)[STRING_PIECE(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
128 (*vars)[STRING_PIECE(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900129 } while (0)
130 INSERT_AUTO_VAR(AutoAtVar, "@");
131 INSERT_AUTO_VAR(AutoLessVar, "<");
132 INSERT_AUTO_VAR(AutoHatVar, "^");
133 INSERT_AUTO_VAR(AutoPlusVar, "+");
134 INSERT_AUTO_VAR(AutoStarVar, "*");
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900135 }
136
137 void ExecNode(DepNode* n, DepNode* needed_by) {
138 if (done_[n->output])
139 return;
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900140 done_[n->output] = true;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900141
142 LOG("ExecNode: %s for %s",
143 n->output.as_string().c_str(),
144 needed_by ? needed_by->output.as_string().c_str() : "(null)");
145
146 for (DepNode* d : n->deps) {
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900147 if (d->is_order_only && Exists(d->output)) {
148 continue;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900149 }
Shinichiro Hamajifdb56dc2015-06-18 19:54:39 +0900150 // TODO: Check the timestamp.
151 if (Exists(d->output)) {
152 continue;
153 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900154 ExecNode(d, n);
155 }
156
157 vector<Runner*> runners;
158 CreateRunners(n, &runners);
159 for (Runner* runner : runners) {
160 if (runner->echo) {
161 printf("%s\n", runner->cmd->c_str());
162 fflush(stdout);
163 }
Shinichiro Hamaji08808d32015-06-26 08:02:45 +0900164 if (!g_is_syntax_check_only) {
165 int result = system(runner->cmd->c_str());
166 if (result != 0) {
167 if (runner->ignore_error) {
168 fprintf(stderr, "[%.*s] Error %d (ignored)\n",
169 SPF(runner->output), WEXITSTATUS(result));
170 } else {
171 fprintf(stderr, "*** [%.*s] Error %d\n",
172 SPF(runner->output), WEXITSTATUS(result));
173 exit(1);
174 }
Shinichiro Hamaji5e9def32015-06-24 22:27:48 +0900175 }
176 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900177 delete runner;
178 }
179 }
180
Shinichiro Hamaji1c448b12015-06-25 21:48:23 +0900181 void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
182 *s = TrimLeftSpace(*s);
183 while (true) {
184 char c = s->get(0);
185 if (c == '@') {
186 *echo = false;
187 } else if (c == '-') {
188 *ignore_error = true;
189 } else {
190 break;
191 }
192 *s = TrimLeftSpace(s->substr(1));
193 }
194 }
195
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900196 void CreateRunners(DepNode* n, vector<Runner*>* runners) {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900197 ev_->set_current_scope(n->rule_vars);
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900198 current_dep_node_ = n;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900199 for (Value* v : n->cmds) {
Shinichiro Hamajia4d0ecb2015-06-24 22:08:30 +0900200 shared_ptr<string> cmds_buf = v->Eval(ev_);
Shinichiro Hamaji1c448b12015-06-25 21:48:23 +0900201 StringPiece cmds = *cmds_buf;
202 bool global_echo = true;
203 bool global_ignore_error = false;
204 ParseCommandPrefixes(&cmds, &global_echo, &global_ignore_error);
Shinichiro Hamaji70bbc4d2015-06-24 22:13:35 +0900205 if (cmds == "")
Shinichiro Hamaji0998b882015-06-24 16:59:18 +0900206 continue;
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900207 while (true) {
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900208 size_t lf_cnt;
209 size_t index = FindEndOfLine(cmds, 0, &lf_cnt);
210 if (index == cmds.size())
211 index = string::npos;
Shinichiro Hamajia4d0ecb2015-06-24 22:08:30 +0900212 StringPiece cmd = TrimLeftSpace(cmds.substr(0, index));
213 cmds = cmds.substr(index + 1);
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900214
Shinichiro Hamaji1c448b12015-06-25 21:48:23 +0900215 bool echo = global_echo;
216 bool ignore_error = global_ignore_error;
217 ParseCommandPrefixes(&cmd, &echo, &ignore_error);
Shinichiro Hamaji14bb2792015-06-25 18:24:11 +0900218
Shinichiro Hamaji70bbc4d2015-06-24 22:13:35 +0900219 if (!cmd.empty()) {
220 Runner* runner = new Runner;
221 runner->output = n->output;
222 runner->cmd = make_shared<string>(cmd.as_string());
223 runner->echo = echo;
224 runner->ignore_error = ignore_error;
225 runners->push_back(runner);
226 }
227 if (index == string::npos)
228 break;
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900229 }
Shinichiro Hamaji133bf672015-06-17 06:14:20 +0900230 continue;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900231 }
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900232 ev_->set_current_scope(NULL);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900233 }
234
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900235 const DepNode* current_dep_node() const { return current_dep_node_; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900236
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900237 private:
238 Vars* vars_;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900239 Evaluator* ev_;
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900240 unordered_map<StringPiece, bool> done_;
241 DepNode* current_dep_node_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900242};
243
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900244void AutoAtVar::Eval(Evaluator*, string* s) const {
245 AppendString(ex_->current_dep_node()->output, s);
246}
247
248void AutoLessVar::Eval(Evaluator*, string* s) const {
249 auto& ai = ex_->current_dep_node()->actual_inputs;
250 if (!ai.empty())
251 AppendString(ai[0], s);
252}
253
254void AutoHatVar::Eval(Evaluator*, string* s) const {
255 unordered_set<StringPiece> seen;
256 WordWriter ww(s);
257 for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
258 if (seen.insert(ai).second)
259 ww.Write(ai);
260 }
261}
262
263void AutoPlusVar::Eval(Evaluator*, string* s) const {
264 WordWriter ww(s);
265 for (StringPiece ai : ex_->current_dep_node()->actual_inputs) {
266 ww.Write(ai);
267 }
268}
269
270void AutoStarVar::Eval(Evaluator*, string* s) const {
271 AppendString(StripExt(ex_->current_dep_node()->output), s);
272}
273
Shinichiro Hamaji22fede42015-06-18 18:38:32 +0900274void AutoSuffixDVar::Eval(Evaluator* ev, string* s) const {
275 string buf;
276 wrapped_->Eval(ev, &buf);
277 WordWriter ww(s);
278 for (StringPiece tok : WordScanner(buf)) {
279 ww.Write(Dirname(tok));
280 }
281}
282
283void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
284 string buf;
285 wrapped_->Eval(ev, &buf);
286 WordWriter ww(s);
287 for (StringPiece tok : WordScanner(buf)) {
288 ww.Write(Basename(tok));
289 }
290}
291
Shinichiro Hamaji7154e8d2015-06-18 18:28:26 +0900292} // namespace
293
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900294void Exec(const vector<DepNode*>& roots, Evaluator* ev) {
295 unique_ptr<Executor> executor(new Executor(ev));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900296 for (DepNode* root : roots) {
297 executor->ExecNode(root, NULL);
298 }
299}