Ninja
build.cc
Go to the documentation of this file.
00001 // Copyright 2011 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //     http://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "build.h"
00016 
00017 #include <assert.h>
00018 #include <stdio.h>
00019 
00020 #ifdef _WIN32
00021 #include <windows.h>
00022 #else
00023 #include <sys/ioctl.h>
00024 #include <sys/time.h>
00025 #include <sys/termios.h>
00026 #endif
00027 
00028 #include "build_log.h"
00029 #include "disk_interface.h"
00030 #include "graph.h"
00031 #include "state.h"
00032 #include "subprocess.h"
00033 #include "util.h"
00034 
00035 /// Tracks the status of a build: completion fraction, printing updates.
00036 struct BuildStatus {
00037   BuildStatus(const BuildConfig& config);
00038   void PlanHasTotalEdges(int total);
00039   void BuildEdgeStarted(Edge* edge);
00040   void BuildEdgeFinished(Edge* edge, bool success, const string& output,
00041                          int* start_time, int* end_time);
00042 
00043  private:
00044   void PrintStatus(Edge* edge);
00045 
00046   const BuildConfig& config_;
00047 
00048   /// Time the build started.
00049   int64_t start_time_millis_;
00050   /// Time we last printed an update.
00051   int64_t last_update_millis_;
00052 
00053   int started_edges_, finished_edges_, total_edges_;
00054 
00055   /// Map of running edge to time the edge started running.
00056   typedef map<Edge*, int> RunningEdgeMap;
00057   RunningEdgeMap running_edges_;
00058 
00059   /// Whether we can do fancy terminal control codes.
00060   bool smart_terminal_;
00061 };
00062 
00063 BuildStatus::BuildStatus(const BuildConfig& config)
00064     : config_(config),
00065       start_time_millis_(GetTimeMillis()),
00066       last_update_millis_(start_time_millis_),
00067       started_edges_(0), finished_edges_(0), total_edges_(0) {
00068 #ifndef WIN32
00069   const char* term = getenv("TERM");
00070   smart_terminal_ = isatty(1) && term && string(term) != "dumb";
00071 #else
00072   smart_terminal_ = false;
00073 #endif
00074 
00075   // Don't do anything fancy in verbose mode.
00076   if (config_.verbosity != BuildConfig::NORMAL)
00077     smart_terminal_ = false;
00078 }
00079 
00080 void BuildStatus::PlanHasTotalEdges(int total) {
00081   total_edges_ = total;
00082 }
00083 
00084 void BuildStatus::BuildEdgeStarted(Edge* edge) {
00085   int start_time = (int)(GetTimeMillis() - start_time_millis_);
00086   running_edges_.insert(make_pair(edge, start_time));
00087   ++started_edges_;
00088 
00089   PrintStatus(edge);
00090 }
00091 
00092 void BuildStatus::BuildEdgeFinished(Edge* edge,
00093                                     bool success,
00094                                     const string& output,
00095                                     int* start_time,
00096                                     int* end_time) {
00097   int64_t now = GetTimeMillis();
00098   ++finished_edges_;
00099 
00100   RunningEdgeMap::iterator i = running_edges_.find(edge);
00101   *start_time = i->second;
00102   *end_time = (int)(now - start_time_millis_);
00103   int total_time = end_time - start_time;
00104   running_edges_.erase(i);
00105 
00106   if (config_.verbosity == BuildConfig::QUIET)
00107     return;
00108 
00109   if (smart_terminal_)
00110     PrintStatus(edge);
00111 
00112   if (success && output.empty()) {
00113     if (smart_terminal_) {
00114       if (finished_edges_ == total_edges_)
00115         printf("\n");
00116     } else {
00117       if (total_time > 5*1000) {
00118         printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
00119                finished_edges_, total_edges_);
00120         last_update_millis_ = now;
00121       }
00122     }
00123   } else {
00124     if (smart_terminal_)
00125       printf("\n");
00126 
00127     // Print the command that is spewing before printing its output.
00128     if (!success)
00129       printf("FAILED: %s\n", edge->EvaluateCommand().c_str());
00130 
00131     if (!output.empty())
00132       printf("%s", output.c_str());
00133   }
00134 }
00135 
00136 void BuildStatus::PrintStatus(Edge* edge) {
00137   if (config_.verbosity == BuildConfig::QUIET)
00138     return;
00139 
00140   bool force_full_command = config_.verbosity == BuildConfig::VERBOSE;
00141 
00142   string to_print = edge->GetDescription();
00143   if (to_print.empty() || force_full_command)
00144     to_print = edge->EvaluateCommand();
00145 
00146   if (smart_terminal_)
00147     printf("\r");  // Print over previous line, if any.
00148 
00149   int progress_chars = printf("[%d/%d] ", started_edges_, total_edges_);
00150 
00151 #ifndef WIN32
00152   if (smart_terminal_ && !force_full_command) {
00153     // Limit output to width of the terminal if provided so we don't cause
00154     // line-wrapping.
00155     winsize size;
00156     if ((ioctl(0, TIOCGWINSZ, &size) == 0) && size.ws_col) {
00157       const int kMargin = progress_chars + 3;  // Space for [xx/yy] and "...".
00158       if (to_print.size() + kMargin > size.ws_col) {
00159         int elide_size = (size.ws_col - kMargin) / 2;
00160         to_print = to_print.substr(0, elide_size)
00161           + "..."
00162           + to_print.substr(to_print.size() - elide_size, elide_size);
00163       }
00164     }
00165   }
00166 #endif
00167 
00168   printf("%s", to_print.c_str());
00169 
00170   if (smart_terminal_ && !force_full_command) {
00171     printf("\e[K");  // Clear to end of line.
00172     fflush(stdout);
00173   } else {
00174     printf("\n");
00175   }
00176 }
00177 
00178 Plan::Plan() : command_edges_(0), wanted_edges_(0) {}
00179 
00180 bool Plan::AddTarget(Node* node, string* err) {
00181   vector<Node*> stack;
00182   return AddSubTarget(node, &stack, err);
00183 }
00184 
00185 bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
00186   Edge* edge = node->in_edge_;
00187   if (!edge) {  // Leaf node.
00188     if (node->dirty_) {
00189       string referenced;
00190       if (!stack->empty())
00191         referenced = ", needed by '" + stack->back()->file_->path_ + "',";
00192       *err = "'" + node->file_->path_ + "'" + referenced + " missing "
00193              "and no known rule to make it";
00194     }
00195     return false;
00196   }
00197   assert(edge);
00198 
00199   if (CheckDependencyCycle(node, stack, err))
00200     return false;
00201 
00202   if (edge->outputs_ready())
00203     return false;  // Don't need to do anything.
00204 
00205   // If an entry in want_ does not already exist for edge, create an entry which
00206   // maps to false, indicating that we do not want to build this entry itself.
00207   pair<map<Edge*, bool>::iterator, bool> want_ins =
00208     want_.insert(make_pair(edge, false));
00209   bool& want = want_ins.first->second;
00210 
00211   // If we do need to build edge and we haven't already marked it as wanted,
00212   // mark it now.
00213   if (node->dirty() && !want) {
00214     want = true;
00215     ++wanted_edges_;
00216     if (find_if(edge->inputs_.begin(), edge->inputs_.end(),
00217                 not1(mem_fun(&Node::ready))) == edge->inputs_.end())
00218       ready_.insert(edge);
00219     if (!edge->is_phony())
00220       ++command_edges_;
00221   }
00222 
00223   if (!want_ins.second)
00224     return true;  // We've already processed the inputs.
00225 
00226   stack->push_back(node);
00227   for (vector<Node*>::iterator i = edge->inputs_.begin();
00228        i != edge->inputs_.end(); ++i) {
00229     if (!AddSubTarget(*i, stack, err) && !err->empty())
00230       return false;
00231   }
00232   assert(stack->back() == node);
00233   stack->pop_back();
00234 
00235   return true;
00236 }
00237 
00238 bool Plan::CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err) {
00239   vector<Node*>::reverse_iterator ri =
00240       find(stack->rbegin(), stack->rend(), node);
00241   if (ri == stack->rend())
00242     return false;
00243 
00244   // Add this node onto the stack to make it clearer where the loop
00245   // is.
00246   stack->push_back(node);
00247 
00248   vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
00249   *err = "dependency cycle: ";
00250   for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
00251     if (i != start)
00252       err->append(" -> ");
00253     err->append((*i)->file_->path_);
00254   }
00255   return true;
00256 }
00257 
00258 Edge* Plan::FindWork() {
00259   if (ready_.empty())
00260     return NULL;
00261   set<Edge*>::iterator i = ready_.begin();
00262   Edge* edge = *i;
00263   ready_.erase(i);
00264   return edge;
00265 }
00266 
00267 void Plan::EdgeFinished(Edge* edge) {
00268   map<Edge*, bool>::iterator i = want_.find(edge);
00269   assert(i != want_.end());
00270   if (i->second)
00271     --wanted_edges_;
00272   want_.erase(i);
00273   edge->outputs_ready_ = true;
00274 
00275   // Check off any nodes we were waiting for with this edge.
00276   for (vector<Node*>::iterator i = edge->outputs_.begin();
00277        i != edge->outputs_.end(); ++i) {
00278     NodeFinished(*i);
00279   }
00280 }
00281 
00282 void Plan::NodeFinished(Node* node) {
00283   // See if we we want any edges from this node.
00284   for (vector<Edge*>::iterator i = node->out_edges_.begin();
00285        i != node->out_edges_.end(); ++i) {
00286     map<Edge*, bool>::iterator want_i = want_.find(*i);
00287     if (want_i == want_.end())
00288       continue;
00289 
00290     // See if the edge is now ready.
00291     if (find_if((*i)->inputs_.begin(), (*i)->inputs_.end(),
00292                 not1(mem_fun(&Node::ready))) == (*i)->inputs_.end()) {
00293       if (want_i->second) {
00294         ready_.insert(*i);
00295       } else {
00296         // We do not need to build this edge, but we might need to build one of
00297         // its dependents.
00298         EdgeFinished(*i);
00299       }
00300     }
00301   }
00302 }
00303 
00304 void Plan::CleanNode(BuildLog* build_log, Node* node) {
00305   node->dirty_ = false;
00306 
00307   for (vector<Edge*>::iterator ei = node->out_edges_.begin();
00308        ei != node->out_edges_.end(); ++ei) {
00309     // Don't process edges that we don't actually want.
00310     map<Edge*, bool>::iterator want_i = want_.find(*ei);
00311     if (want_i == want_.end() || !want_i->second)
00312       continue;
00313 
00314     // If all non-order-only inputs for this edge are now clean,
00315     // we might have changed the dirty state of the outputs.
00316     vector<Node*>::iterator begin = (*ei)->inputs_.begin(),
00317                             end = (*ei)->inputs_.end() - (*ei)->order_only_deps_;
00318     if (find_if(begin, end, mem_fun(&Node::dirty)) == end) {
00319       // Recompute most_recent_input and command.
00320       time_t most_recent_input = 1;
00321       for (vector<Node*>::iterator ni = begin; ni != end; ++ni)
00322         if ((*ni)->file_->mtime_ > most_recent_input)
00323           most_recent_input = (*ni)->file_->mtime_;
00324       string command = (*ei)->EvaluateCommand();
00325 
00326       // Now, recompute the dirty state of each output.
00327       bool all_outputs_clean = true;
00328       for (vector<Node*>::iterator ni = (*ei)->outputs_.begin();
00329            ni != (*ei)->outputs_.end(); ++ni) {
00330         if (!(*ni)->dirty_)
00331           continue;
00332 
00333         // RecomputeOutputDirty will not modify dirty_ if the output is clean.
00334         (*ni)->dirty_ = false;
00335 
00336         // Since we know that all non-order-only inputs are clean, we can pass
00337         // "false" as the "dirty" argument here.
00338         (*ei)->RecomputeOutputDirty(build_log, most_recent_input, false,
00339                                     command, *ni);
00340         if ((*ni)->dirty_) {
00341           all_outputs_clean = false;
00342         } else {
00343           CleanNode(build_log, *ni);
00344         }
00345       }
00346 
00347       // If we cleaned all outputs, mark the node as not wanted.
00348       if (all_outputs_clean) {
00349         want_i->second = false;
00350         --wanted_edges_;
00351         if (!(*ei)->is_phony())
00352           --command_edges_;
00353       }
00354     }
00355   }
00356 }
00357 
00358 void Plan::Dump() {
00359   printf("pending: %d\n", (int)want_.size());
00360   for (map<Edge*, bool>::iterator i = want_.begin(); i != want_.end(); ++i) {
00361     if (i->second)
00362       printf("want ");
00363     i->first->Dump();
00364   }
00365   printf("ready: %d\n", (int)ready_.size());
00366 }
00367 
00368 struct RealCommandRunner : public CommandRunner {
00369   RealCommandRunner(const BuildConfig& config) : config_(config) {}
00370   virtual ~RealCommandRunner() {}
00371   virtual bool CanRunMore();
00372   virtual bool StartCommand(Edge* edge);
00373   virtual Edge* WaitForCommand(bool* success, string* output);
00374 
00375   const BuildConfig& config_;
00376   SubprocessSet subprocs_;
00377   map<Subprocess*, Edge*> subproc_to_edge_;
00378 };
00379 
00380 bool RealCommandRunner::CanRunMore() {
00381   return ((int)subprocs_.running_.size()) < config_.parallelism;
00382 }
00383 
00384 bool RealCommandRunner::StartCommand(Edge* edge) {
00385   string command = edge->EvaluateCommand();
00386   Subprocess* subproc = new Subprocess;
00387   subproc_to_edge_.insert(make_pair(subproc, edge));
00388   if (!subproc->Start(&subprocs_, command))
00389     return false;
00390 
00391   subprocs_.Add(subproc);
00392   return true;
00393 }
00394 
00395 Edge* RealCommandRunner::WaitForCommand(bool* success, string* output) {
00396   Subprocess* subproc;
00397   while ((subproc = subprocs_.NextFinished()) == NULL) {
00398     subprocs_.DoWork();
00399   }
00400 
00401   *success = subproc->Finish();
00402   *output = subproc->GetOutput();
00403 
00404   map<Subprocess*, Edge*>::iterator i = subproc_to_edge_.find(subproc);
00405   Edge* edge = i->second;
00406   subproc_to_edge_.erase(i);
00407 
00408   delete subproc;
00409   return edge;
00410 }
00411 
00412 /// A CommandRunner that doesn't actually run the commands.
00413 struct DryRunCommandRunner : public CommandRunner {
00414   virtual ~DryRunCommandRunner() {}
00415   virtual bool CanRunMore() {
00416     return true;
00417   }
00418   virtual bool StartCommand(Edge* edge) {
00419     finished_.push(edge);
00420     return true;
00421   }
00422   virtual Edge* WaitForCommand(bool* success, string* output) {
00423     if (finished_.empty())
00424       return NULL;
00425     *success = true;
00426     Edge* edge = finished_.front();
00427     finished_.pop();
00428     return edge;
00429   }
00430 
00431   queue<Edge*> finished_;
00432 };
00433 
00434 Builder::Builder(State* state, const BuildConfig& config)
00435     : state_(state), config_(config) {
00436   disk_interface_ = new RealDiskInterface;
00437   if (config.dry_run)
00438     command_runner_ = new DryRunCommandRunner;
00439   else
00440     command_runner_ = new RealCommandRunner(config);
00441   status_ = new BuildStatus(config);
00442   log_ = state->build_log_;
00443 }
00444 
00445 Node* Builder::AddTarget(const string& name, string* err) {
00446   Node* node = state_->LookupNode(name);
00447   if (!node) {
00448     *err = "unknown target: '" + name + "'";
00449     return NULL;
00450   }
00451   if (!AddTarget(node, err))
00452     return NULL;
00453   return node;
00454 }
00455 
00456 bool Builder::AddTarget(Node* node, string* err) {
00457   node->file_->StatIfNecessary(disk_interface_);
00458   if (Edge* in_edge = node->in_edge_) {
00459     if (!in_edge->RecomputeDirty(state_, disk_interface_, err))
00460       return false;
00461     if (in_edge->outputs_ready())
00462       return true;  // Nothing to do.
00463   }
00464 
00465   if (!plan_.AddTarget(node, err))
00466     return false;
00467 
00468   return true;
00469 }
00470 
00471 bool Builder::AlreadyUpToDate() const {
00472   return !plan_.more_to_do();
00473 }
00474 
00475 bool Builder::Build(string* err) {
00476   assert(!AlreadyUpToDate());
00477 
00478   status_->PlanHasTotalEdges(plan_.command_edge_count());
00479   int pending_commands = 0;
00480   int failures_allowed = config_.swallow_failures;
00481 
00482   // This main loop runs the entire build process.
00483   // It is structured like this:
00484   // First, we attempt to start as many commands as allowed by the
00485   // command runner.
00486   // Second, we attempt to wait for / reap the next finished command.
00487   // If we can do neither of those, the build is stuck, and we report
00488   // an error.
00489   while (plan_.more_to_do()) {
00490     // See if we can start any more commands.
00491     if (command_runner_->CanRunMore()) {
00492       if (Edge* edge = plan_.FindWork()) {
00493         if (!StartEdge(edge, err))
00494           return false;
00495 
00496         if (edge->is_phony())
00497           FinishEdge(edge, true, "");
00498         else
00499           ++pending_commands;
00500 
00501         // We made some progress; go back to the main loop.
00502         continue;
00503       }
00504     }
00505 
00506     // See if we can reap any finished commands.
00507     if (pending_commands) {
00508       bool success;
00509       string output;
00510       Edge* edge;
00511       if ((edge = command_runner_->WaitForCommand(&success, &output))) {
00512         --pending_commands;
00513         FinishEdge(edge, success, output);
00514         if (!success) {
00515           if (failures_allowed-- == 0) {
00516             if (config_.swallow_failures != 0)
00517               *err = "subcommands failed";
00518             else
00519               *err = "subcommand failed";
00520             return false;
00521           }
00522         }
00523 
00524         // We made some progress; start the main loop over.
00525         continue;
00526       }
00527     }
00528 
00529     // If we get here, we can neither enqueue new commands nor are any running.
00530     if (pending_commands) {
00531       *err = "stuck: pending commands but none to wait for? [this is a bug]";
00532       return false;
00533     }
00534 
00535     // If we get here, we cannot make any more progress.
00536     if (failures_allowed < config_.swallow_failures) {
00537       *err = "cannot make progress due to previous errors";
00538       return false;
00539     } else {
00540       *err = "stuck [this is a bug]";
00541       return false;
00542     }
00543   }
00544 
00545   return true;
00546 }
00547 
00548 bool Builder::StartEdge(Edge* edge, string* err) {
00549   if (edge->is_phony())
00550     return true;
00551 
00552   status_->BuildEdgeStarted(edge);
00553 
00554   // Create directories necessary for outputs.
00555   // XXX: this will block; do we care?
00556   for (vector<Node*>::iterator i = edge->outputs_.begin();
00557        i != edge->outputs_.end(); ++i) {
00558     if (!disk_interface_->MakeDirs((*i)->file_->path_))
00559       return false;
00560   }
00561 
00562   // Compute command and start it.
00563   string command = edge->EvaluateCommand();
00564   if (!command_runner_->StartCommand(edge)) {
00565     err->assign("command '" + command + "' failed.");
00566     return false;
00567   }
00568 
00569   return true;
00570 }
00571 
00572 void Builder::FinishEdge(Edge* edge, bool success, const string& output) {
00573   time_t restat_mtime = 0;
00574 
00575   if (success) {
00576     if (edge->rule_->restat_) {
00577       bool node_cleaned = false;
00578 
00579       for (vector<Node*>::iterator i = edge->outputs_.begin();
00580            i != edge->outputs_.end(); ++i) {
00581         if ((*i)->file_->exists()) {
00582           time_t new_mtime = disk_interface_->Stat((*i)->file_->path_);
00583           if ((*i)->file_->mtime_ == new_mtime) {
00584             // The rule command did not change the output.  Propagate the clean
00585             // state through the build graph.
00586             plan_.CleanNode(log_, *i);
00587             node_cleaned = true;
00588           }
00589         }
00590       }
00591 
00592       if (node_cleaned) {
00593         // If any output was cleaned, find the most recent mtime of any
00594         // (existing) non-order-only input.
00595         for (vector<Node*>::iterator i = edge->inputs_.begin();
00596              i != edge->inputs_.end() - edge->order_only_deps_; ++i) {
00597           time_t input_mtime = disk_interface_->Stat((*i)->file_->path_);
00598           if (input_mtime == 0) {
00599             restat_mtime = 0;
00600             break;
00601           }
00602           if (input_mtime > restat_mtime)
00603             restat_mtime = input_mtime;
00604         }
00605 
00606         // The total number of edges in the plan may have changed as a result
00607         // of a restat.
00608         status_->PlanHasTotalEdges(plan_.command_edge_count());
00609       }
00610     }
00611 
00612     plan_.EdgeFinished(edge);
00613   }
00614 
00615   if (edge->is_phony())
00616     return;
00617 
00618   int start_time, end_time;
00619   status_->BuildEdgeFinished(edge, success, output, &start_time, &end_time);
00620   if (success && log_)
00621     log_->RecordCommand(edge, start_time, end_time, restat_mtime);
00622 }