1 // 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 15 // +build ignore 16 17 #include "exec.h" 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 22 #include <memory> 23 #include <unordered_map> 24 #include <utility> 25 #include <vector> 26 27 #include "command.h" 28 #include "dep.h" 29 #include "eval.h" 30 #include "expr.h" 31 #include "fileutil.h" 32 #include "flags.h" 33 #include "log.h" 34 #include "string_piece.h" 35 #include "strutil.h" 36 #include "symtab.h" 37 #include "var.h" 38 39 namespace { 40 41 const double kNotExist = -2.0; 42 const double kProcessing = -1.0; 43 44 class Executor { 45 public: 46 explicit Executor(Evaluator* ev) 47 : ce_(ev), 48 num_commands_(0) { 49 shell_ = ev->GetShell(); 50 shellflag_ = ev->GetShellFlag(); 51 } 52 53 double ExecNode(DepNode* n, DepNode* needed_by) { 54 auto found = done_.find(n->output); 55 if (found != done_.end()) { 56 if (found->second == kProcessing) { 57 WARN("Circular %s <- %s dependency dropped.", 58 needed_by ? needed_by->output.c_str() : "(null)", 59 n->output.c_str()); 60 } 61 return found->second; 62 } 63 done_[n->output] = kProcessing; 64 double output_ts = GetTimestamp(n->output.c_str()); 65 66 LOG("ExecNode: %s for %s", 67 n->output.c_str(), 68 needed_by ? needed_by->output.c_str() : "(null)"); 69 70 if (!n->has_rule && output_ts == kNotExist && !n->is_phony) { 71 if (needed_by) { 72 ERROR("*** No rule to make target '%s', needed by '%s'.", 73 n->output.c_str(), needed_by->output.c_str()); 74 } else { 75 ERROR("*** No rule to make target '%s'.", n->output.c_str()); 76 } 77 } 78 79 double latest = kProcessing; 80 for (DepNode* d : n->order_onlys) { 81 if (Exists(d->output.str())) { 82 continue; 83 } 84 double ts = ExecNode(d, n); 85 if (latest < ts) 86 latest = ts; 87 } 88 89 for (DepNode* d : n->deps) { 90 double ts = ExecNode(d, n); 91 if (latest < ts) 92 latest = ts; 93 } 94 95 if (output_ts >= latest && !n->is_phony) { 96 done_[n->output] = output_ts; 97 return output_ts; 98 } 99 100 vector<Command*> commands; 101 ce_.Eval(n, &commands); 102 for (Command* command : commands) { 103 num_commands_ += 1; 104 if (command->echo) { 105 printf("%s\n", command->cmd.c_str()); 106 fflush(stdout); 107 } 108 if (!g_flags.is_dry_run) { 109 string out; 110 int result = RunCommand(shell_, shellflag_, 111 command->cmd.c_str(), 112 RedirectStderr::STDOUT, 113 &out); 114 printf("%s", out.c_str()); 115 if (result != 0) { 116 if (command->ignore_error) { 117 fprintf(stderr, "[%s] Error %d (ignored)\n", 118 command->output.c_str(), WEXITSTATUS(result)); 119 } else { 120 fprintf(stderr, "*** [%s] Error %d\n", 121 command->output.c_str(), WEXITSTATUS(result)); 122 exit(1); 123 } 124 } 125 } 126 delete command; 127 } 128 129 done_[n->output] = output_ts; 130 return output_ts; 131 } 132 133 uint64_t Count() { 134 return num_commands_; 135 } 136 137 private: 138 CommandEvaluator ce_; 139 unordered_map<Symbol, double> done_; 140 string shell_; 141 string shellflag_; 142 uint64_t num_commands_; 143 }; 144 145 } // namespace 146 147 void Exec(const vector<DepNode*>& roots, Evaluator* ev) { 148 unique_ptr<Executor> executor(new Executor(ev)); 149 for (DepNode* root : roots) { 150 executor->ExecNode(root, NULL); 151 } 152 if (executor->Count() == 0) { 153 for (DepNode* root : roots) { 154 printf("kati: Nothing to be done for `%s'.\n", root->output.c_str()); 155 } 156 } 157 } 158