aboutsummaryrefslogtreecommitdiffstats
path: root/src/exec.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/exec.cc')
-rw-r--r--src/exec.cc151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/exec.cc b/src/exec.cc
new file mode 100644
index 0000000..75f5358
--- /dev/null
+++ b/src/exec.cc
@@ -0,0 +1,151 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build ignore
+
+#include "exec.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+#include <memory>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "command.h"
+#include "dep.h"
+#include "eval.h"
+#include "expr.h"
+#include "fileutil.h"
+#include "flags.h"
+#include "log.h"
+#include "string_piece.h"
+#include "strutil.h"
+#include "symtab.h"
+#include "var.h"
+
+namespace {
+
+const double kNotExist = -2.0;
+const double kProcessing = -1.0;
+
+class Executor {
+ public:
+ explicit Executor(Evaluator* ev) : ce_(ev), num_commands_(0) {
+ shell_ = ev->GetShell();
+ shellflag_ = ev->GetShellFlag();
+ }
+
+ double ExecNode(DepNode* n, DepNode* needed_by) {
+ auto found = done_.find(n->output);
+ if (found != done_.end()) {
+ if (found->second == kProcessing) {
+ WARN("Circular %s <- %s dependency dropped.",
+ needed_by ? needed_by->output.c_str() : "(null)",
+ n->output.c_str());
+ }
+ return found->second;
+ }
+ done_[n->output] = kProcessing;
+ double output_ts = GetTimestamp(n->output.c_str());
+
+ LOG("ExecNode: %s for %s", n->output.c_str(),
+ needed_by ? needed_by->output.c_str() : "(null)");
+
+ if (!n->has_rule && output_ts == kNotExist && !n->is_phony) {
+ if (needed_by) {
+ ERROR("*** No rule to make target '%s', needed by '%s'.",
+ n->output.c_str(), needed_by->output.c_str());
+ } else {
+ ERROR("*** No rule to make target '%s'.", n->output.c_str());
+ }
+ }
+
+ double latest = kProcessing;
+ for (auto const& d : n->order_onlys) {
+ if (Exists(d.second->output.str())) {
+ continue;
+ }
+ double ts = ExecNode(d.second, n);
+ if (latest < ts)
+ latest = ts;
+ }
+
+ for (auto const& d : n->deps) {
+ double ts = ExecNode(d.second, n);
+ if (latest < ts)
+ latest = ts;
+ }
+
+ if (output_ts >= latest && !n->is_phony) {
+ done_[n->output] = output_ts;
+ return output_ts;
+ }
+
+ vector<Command*> commands;
+ ce_.Eval(n, &commands);
+ for (Command* command : commands) {
+ num_commands_ += 1;
+ if (command->echo) {
+ printf("%s\n", command->cmd.c_str());
+ fflush(stdout);
+ }
+ if (!g_flags.is_dry_run) {
+ string out;
+ int result = RunCommand(shell_, shellflag_, command->cmd.c_str(),
+ RedirectStderr::STDOUT, &out);
+ printf("%s", out.c_str());
+ if (result != 0) {
+ if (command->ignore_error) {
+ fprintf(stderr, "[%s] Error %d (ignored)\n",
+ command->output.c_str(), WEXITSTATUS(result));
+ } else {
+ fprintf(stderr, "*** [%s] Error %d\n", command->output.c_str(),
+ WEXITSTATUS(result));
+ exit(1);
+ }
+ }
+ }
+ delete command;
+ }
+
+ done_[n->output] = output_ts;
+ return output_ts;
+ }
+
+ uint64_t Count() { return num_commands_; }
+
+ private:
+ CommandEvaluator ce_;
+ unordered_map<Symbol, double> done_;
+ string shell_;
+ string shellflag_;
+ uint64_t num_commands_;
+};
+
+} // namespace
+
+void Exec(const vector<NamedDepNode>& roots, Evaluator* ev) {
+ unique_ptr<Executor> executor(new Executor(ev));
+ for (auto const& root : roots) {
+ executor->ExecNode(root.second, NULL);
+ }
+ if (executor->Count() == 0) {
+ for (auto const& root : roots) {
+ printf("kati: Nothing to be done for `%s'.\n", root.first.c_str());
+ }
+ }
+}